оператор перегрузки = - PullRequest
       21

оператор перегрузки =

0 голосов
/ 30 августа 2011

Мне нужно создать функцию, которая перегружает оператор =, чтобы при вводе object1 = object2; он копировал все значения внутри объекта2 в объект1.

Мой класс выглядит так:

class foo {
  private:
    int max;
    int *val;
    size_t *listofVal;
}

И моя функция перегрузки объявлена ​​как:

foo& foo::operator=(const foo& matrix);

foo::foo(std::istream& s);  //constructor

как бы я это сделал?

Ответы [ 3 ]

5 голосов
/ 30 августа 2011

Лучший способ сделать это - использовать Копировать и поменять местами Идиома.
Также обратите внимание, что если вы чувствуете необходимость перегрузки оператора назначения копирования , то вам также, вероятно, потребуется перегрузить конструктор копирования , а также деструктор для вашего класса. .

Взгляните на Правило трех .

1 голос
/ 30 августа 2011

Простое копирование всех значений - это поведение по умолчанию компилятора копирования, предоставляемого компилятором. Это называется «мелкой копией».

Более сложное поведение достигается путем реализации собственного конструктора, чтобы объекты (здесь значения), на которые указывает ваша ссылка, создавались заново в копии.

foo::foo(std::istream& s) {
    max = s.max;
    val = new int;
    *val = s->val;
    listofVal = new size_t;
    *listofVal = s->listofVal;
}

будет одним из способов достижения того, что известно как «глубокая копия».

Но так как один из ваших членов называется listofVal Я скорее чувствую, что вы делаете что-то иное, чем сохранение одного значения по адресу памяти, на который оно указывает, и в этом случае вы должны использовать счетчик для количества элементов, содержащихся в нем. , который я и впредь буду считать полем, которое вы называете max. Чтобы скопировать весь список, ваш конструктор копирования должен быть:

foo::foo(std::istream& s) {
    max = s.max;
    val = new int;
    *val = s->val;
    listofVal = new size_t[max];
    for (int i = 0; i < max; ++i)
        listofVal[i] = s->listofVal[i];
}

Рави, да, конструктор копирования является доказательством конструкции, и, несмотря на нарушение «Правила Три», может быть реализован раньше двух других. Вот оператор присваивания.

foo& foo::operator=(const foo& matrix) {
    if (this != matrix) {
        max = matrix.max;
        val = new int;
        *val = matrix->val;
        listofVal = new size_t[max];
        for (int i = 0; i < max; ++i)
            listofVal[i] = matrix->listofVal[i];
    }
}

подходит для назначения object1 = object2;. Я склоняюсь к подходу конструктора копирования.

Методы должны быть членами для доступа к частным данным, поэтому ваш класс должен выглядеть как

class foo {
    ///...///As before
    foo &operator=(const foo& matrix);
};

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

Исходя из ссылки на идиому «Копировать и поменять», когда LHS может уже содержать данные, для надежного назначения вы можете рассмотреть:

foo& foo::operator=(const foo& matrix) {
    if (this != matrix) {
        val = new int;
        *val = matrix->val;
        size_t* newArray = new size_t[max];
        int newMax = matrix.max;
        std::copy(matrix.listofVal, matrix.listofVal + max, newArray);
        if (listofVal) delete listofVal;
        listofVal = newArray;
        max = newMax;
    }
}

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

0 голосов
/ 30 августа 2011

Google для «Оператора присваивания C ++» дает вам этот полезный сайт ; -)

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