Почему я получаю сообщение об ошибке, когда перегружаю << для объекта, возвращаемого перегруженной функцией оператора +

class String
{
    char* array;
public:
    String(const char* s)
    {
        array = new char[strlen(s) + 1]{ '\0' };
        strcpy(array, s);
    }
    ~String()
    {
        if (array)
        {
            delete[]array;
        }
    }
    String operator+ (const char* p)   //返回对象
    {
        String temp(p);
        char* tempStr = temp.array;
        temp.array = new char[strlen(array) + strlen(tempStr) + 1]{ '\0' };
        strcpy(temp.array, array);
        strcat(temp.array, p);
        delete[]tempStr;
        return temp;
    }
    friend ostream& operator<<(ostream& output, String& x);   // <<函数重载只能定义成友元
};

ostream& operator << (ostream& output, String& x)  //对<<重载的方式
{
    output << x.array;
    return output;
}

int main()
{
    String string1("mystring");
    cout << string1 + "ab" << endl;
    cout << string1 << endl;
    return 0;
}

Я впервые задаю вопрос здесь, поэтому, пожалуйста, простите меня, если есть какие-то плохие описания :)

Возвращаясь к делу, я перегрузил операторы + и <<, поэтому я хочу получить вывод «mystringab» с помощью cout<<string1+"ab"<<endl, но вывод искажен.

Я думаю, что может быть проблема с перегруженной функцией оператора +, может кто-нибудь, пожалуйста, скажите мне, в чем проблема?

И если я хочу получить правильный результат, как мне переписать перегруженную функцию?

Сделайте второй параметр operator<< a const String&.

Anoop Rana 11.05.2022 19:11

Спасибо, но я только что попробовал, и он все еще выводит искаженные символы :(

Mr Right 11.05.2022 19:22

Смотрите мой ответ ниже и этот рабочая демонстрация. Также не забудьте убедиться, что в вашей программе нет неопределенного поведения.

Anoop Rana 11.05.2022 19:23

Большое спасибо за ваш ответ :) Я изучаю объектно-ориентированное программирование, поэтому я не очень понимаю некоторые механизмы.

Mr Right 11.05.2022 19:30

позже посмотрю внимательнее

Mr Right 11.05.2022 19:39
delete[]tempStr; прямо перед тем, как return temp; освободит буфер принадлежит по темп. Это фатально.
user4581301 11.05.2022 19:39
String не соблюдает правило трех или друзья. Это означает, что его нельзя безопасно скопировать. Передача или возврат по значению приведет к созданию копий. String operator+ (const char* p) возвращается по значению, делает копию и, таким образом, будет фатальным.
user4581301 11.05.2022 19:41

как мне переписать перегруженную функцию по значению

Mr Right 11.05.2022 19:46

Тактическое примечание: если вы добавите учетную переменную для отслеживания длины строки, вы сможете сэкономить на вызовах strlen снова и снова.

user4581301 11.05.2022 19:46

Вам нужно возвращать значение из operator+, это означает, что вы должны сделать String копируемым (или переписать, чтобы гарантировать исключение, но копируемый класс гораздо полезнее, чем тот, который не удастся скопировать). Прочтите размещенную ссылку о Правило трех.

user4581301 11.05.2022 19:52

Я предлагаю задать второй вопрос, который конкретно касается улучшения operator+, потому что Stack Overflow лучше всего работает, когда решает одну проблему на каждый вопрос. Однако в опубликованной ссылке Каковы основные правила и идиомы перегрузки операторов? есть очень важные предложения, которые могут устранить необходимость в этом вопросе.

user4581301 11.05.2022 19:53

Я думал об этом несколько часов и, наконец, понял, где ошибся. Когда temp возвращается, конструктор копирования, написанный самим компилятором, вызывается для создания shallow copy, тем самым создавая анонимный объект, char *array этого анонимного объекта и temp.array указывают на один и тот же адрес, поэтому, когда функция завершается и temp уничтожается , char *array анонимного объекта также удаляется, поэтому будут выводиться искаженные символы. Решение состоит в том, чтобы самостоятельно определить конструктор копирования, чтобы сделать глубокую копию.

Mr Right 12.05.2022 00:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
13
49
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что второй параметр перегруженного operator<< не может быть привязан к String rvalue, поскольку вторым параметром является lvalue ссылка на неконстантный String.

how should I rewrite the overloaded function?

Вам нужно сделать второй параметр перегруженным operator<< a const String&, чтобы он мог работать и со вторым аргументом "ab", как показано ниже:

//---------------------------------------- vvvvv------------>low-level const added here
friend ostream& operator<<(ostream& output,const String& x);

Точно так же сделайте то же самое в определении:

//----------------------------------- vvvvv------------>low-level const added here
ostream& operator << (ostream& output,const String& x) 
{
    output << x.array;
    return output;
}

Кроме того, убедитесь, что ваша программа не имеет неопределенного поведения. Например, убедитесь, что вы используете delete или delete[] только тогда, когда это безопасно (те данные, на которые указывает указатель, больше не нужны). Вы можете использовать такие инструменты, как valgrind, для обнаружения некоторых основных проблем.

Другие вопросы по теме