Присваивание объектов
Один объект можно присвоить другому, если оба объекта имеют одинаковый тип. По умолчанию, когда объект A присваивается объекту B, то осуществляется побитовое копирование всех элементов-данных A в соответствующие элементы-данные B. Если объекты имеют разные типов разные, то компилятор выдаст сообщение об ошибке. Важно понимать, одинаковыми должны быть имена типов, а не их физическое содержание. Например, следующие два типа несовместимы.
class ClassName1
{
int a, b;
public:
void set (int ia, int ib) {a=ia; b=ib;}
};
class ClassName2
{
int a, b;
public:
void set (int ia, int ib) {a=ia; b=ib;}
};
Так что попытка выполнить
ClassName1 c1;
ClassName2 c2;
c2 = c1;
окажется неудачной.
Важно понимать, что при присваивании происходит побитное копирование элементов данных, в том числе и массивов. Особенно внимательным нужно быть при присваивании объектов, в описании типа которых содержатся указатели. Например,
class Pair
{
int a, *b;
public:
void set (int ia, int ib) {a=ia; *b=ib;}
int getb (){return *b;}
int geta (){return a;}
};
main()
{
Pair c1,c2;
c1.set(10,11);
c2 = c1;
c1.set(100,111);
cout << 'с2.b = '<< c2.getb();
}
В результате работы программы получим "c2.b = 111", а не 11, как ожидалось.
Чтобы избежать такого рода недоразумений, используют перегруженный оператор присваивания, в которой явным образом описается (т.е. контролируется) процесс присваивания элементов-данных одного объекта соответствующим элементам-данных другого объекта.
class Pair
{
int a, *b;
public:
Pair operator = (Pair p)
{
a = p.a;
*b = *(p.b);
return *this;
}
...
};
А вот как теперь будет выглядеть наш пример с трехмерным вектором.
class _3d
{
double x, y, z;
public:
_3d ();
_3d (double initX, double initY, double initZ);
double mod () {return sqrt (x*x + y*y +z*z);}
double projection (_3d r) {return (x*r.x + y*r.y + z*r.z) / mod();}
_3d operator + (_3d b);
_3d operator = (_3d b);
};
_3d _3d::operator = (_3d b)
{
x = b.x;
y = b.y;
z = b.z;
return *this;
}
Наивно было бы предполагать, что для каждой новой переменной типа _3d создается копия функции, реализующей операторы "+" и "=". Каждая функция представлена в единственном экземпляре и в момент вызова получает один скрытый параметр - указатель на экземпляр переменной, для которого она вызвана. Этот указатель имеет имя this. Если используемая переменная не описана внутри функции, не является глобальной, то считается, что она является членом структуры и принадлежит рабочей переменной this. Поэтому при реализации функций операторов мы опускали путь доступа к полям структуры, для которой этот оператор будет вызываться.
В качестве аргументов функций-операторов выступают операнды, а возвращаемое значение - результат применения оператора. В частности для оператора "=" это необходимо, чтобы обеспечить возможность последовательного присваивания (a=b=c). Бинарные операторы имеют один аргумент - второй передается через указатель this. Унарные, соответственно, один - this.