Операторы присваивания класса - PullRequest
2 голосов
/ 22 декабря 2010

Я сделал следующий тест на перегрузку оператора:

#include <iostream>
#include <string>

using namespace std;

class TestClass
{
    string ClassName;

    public:

    TestClass(string Name)
    {
        ClassName = Name;
        cout << ClassName << " constructed." << endl;
    }

    ~TestClass()
    {
        cout << ClassName << " destructed." << endl;
    }

    void operator=(TestClass Other)
    {
        cout << ClassName << " in operator=" << endl;
        cout << "The address of the other class is " << &Other << "." << endl;
    }
};

int main()
{
    TestClass FirstInstance("FirstInstance");
    TestClass SecondInstance("SecondInstance");

    FirstInstance = SecondInstance;
    SecondInstance = FirstInstance;

    return 0;
}

Оператор присваивания работает как ожидалось, выводя адрес другого экземпляра.

Теперь, как бы я на самом деле присвоил что-то из другого экземпляра? Например, что-то вроде этого:

void operator=(TestClass Other)
{
    ClassName = Other.ClassName;
}

Ответы [ 5 ]

5 голосов
/ 22 декабря 2010

Код, который вы показали, сделает это.Никто не посчитает, что это будет особенно хорошая реализация.

Это соответствует тому, что ожидается от оператора присваивания:

TestClass& operator=(TestClass other)
{
    using std::swap;
    swap(ClassName, other.ClassName);
    // repeat for other member variables;
    return *this;
}

Кстати, вы говорите о «другом классе»,но у вас есть только один класс и несколько экземпляров этого класса.

5 голосов
/ 22 декабря 2010

Традиционная каноническая форма оператора присваивания выглядит следующим образом:

TestClass& operator=(const TestClass& Other);

(вы также не хотите вызывать конструктор копирования для присваивания), и он возвращает ссылку на *this.

Наивная реализация присваивает каждому элементу данных индивидуально:

TestClass& operator=(const TestClass& Other)
{
  ClassName = Other.ClassName;
  return *this;
}

(Обратите внимание, что это именно то, что должен делать сгенерированный компилятором оператор присваивания, так что перегрузить его довольно бесполезно. Я так понимаю, что это для тренировки.)

Лучше всего было бы использовать идиому Копирование и замена . (Если вы найдете ответ GMan слишком ошеломляющим, попробуйте mine , который менее исчерпывающий. :)) Обратите внимание, что C & S использует конструктор копирования и деструктор для выполнения присваивания и, следовательно, требует, чтобы объект передавался для каждой копии, как у вас в вопросе:

TestClass& operator=(TestClass Other)
3 голосов
/ 22 декабря 2010

почти все сказано, несколько замечаний:

  • проверка на самоназначение, т. Е. if (&other != this) // assign
  • . Здесь вы найдете отличное руководство по перегрузке оператора
1 голос
/ 22 декабря 2010

Традиционно оператор присваивания и конструктор копирования определяются с использованием константной ссылки, а не с помощью механизма копирования по значению.

class TestClass 
{
public:
    //... 
    TestClass& operator=(const TestClass& Other)
    {
        m_ClassName= Other.m_ClassName;
        return *this;
    }
private:
    std::string m_ClassName;
 }

РЕДАКТИРОВАТЬ: я исправил, потому что я поместил код, который не возвращает TestClass & (см. Ответ @sbi)

0 голосов
/ 22 декабря 2010

Вы правы относительно того, как скопировать содержимое из другого класса.Простые объекты можно просто назначить с помощью operator=.

Однако, будьте осторожны со случаями, когда TestClass содержит элементы указателя - если вы просто назначите указатель с помощью operator=, тогда оба объекта будут иметь указатели, указывающиев ту же память, которая может быть не то, что вы хотите.Вместо этого вам может потребоваться выделить некоторую новую память и скопировать в нее указанные данные, чтобы оба объекта имели свою собственную копию данных.Помните, что вам также нужно правильно освободить память, уже указанную назначенным объектом, прежде чем выделять новый блок для скопированных данных.

Кстати, вы, вероятно, должны объявить свой operator= следующим образом:

TestClass & operator=(const TestClass & Other)
{
    ClassName = Other.ClassName;
    return *this;
}

Это общее соглашение, используемое при перегрузке operator=.Оператор return позволяет объединять назначения (например, a = b = c) и передавать параметр по ссылке const, избегая копирования Other на своем пути в вызов функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...