Когда мы должны сделать оператор присваивания приватным и не реализовывать
Это старый экзаменационный вопрос, который просит нас писать операторы присваивания и копировать конструкторы, деструкторы, когда это имеет смысл.
Учитывая следующий код:
class U { /* code not specified here */ };
class A { /* code not specified here */ private: U& u_; };
Я узнал, что Ответ таков: A содержит ссылку C++ на экземпляр U, который можно скопировать, но нельзя сбросить. Поэтому вы должны:
• Написать конструктор копирования, который инициализирует свой U тому же экземпляру, на который ссылается исходный экземпляр A.
• Сделайте свой оператор присваивания частным и не реализуйте
Я знаю, что ссылка не может быть сброшена. Однако означает ли это, что я никогда не смогу использовать оператор присваивания, когда класс содержит данные ссылочного члена? Имеет ли смысл следующий код? Следующий код написан мной (это не ответ)
class U{
public:
int u;
};
class A{
public:
A(U& u):u_(u){}
A& operator=(const A& a){
u_ = a.u_;
return *this;
}
U& u_;
};
int main(){
U u1;
U u2;
A a1(u1);
A a2(u2);
a1 = a2;
a1.u_.u = 1;
a2.u_.u = 2;
cout << "a1.u_.u : " << a1.u_.u << endl;
cout << "a2.u_.u : " << a2.u_.u << endl;
}
Заранее спасибо.
5 ответов
A& operator=(const A& a){
u_ = a.u_;
return *this;
}
Не будет работать, как ожидалось, U
контрольные точки будут назначены.
Конечно, вы можете реализовать оператор присваивания, даже если класс содержит ссылку, при условии, что эта ссылка может быть назначена (что, если указанный класс имеет operator=
только приват?) а ссылка не const U&
(таким образом, не может быть назначен).
Ссылки не могут быть изменены, чтобы ссылаться на что-то еще. Однако вы можете делать то, что вы делаете здесь, потому что делаете:
u_ = a.u_;
в действительности изменяется значение, на которое ссылаются. Он отмечает изменение, на которое ссылается значение.
Означает ли это, что я никогда не смогу использовать оператор присваивания, когда класс содержит данные ссылочного члена?
У вас может быть оператор присваивания, вы просто не можете переназначить ссылку и, следовательно, должны переопределить ожидаемое поведение оператора присваивания.
Ссылки можно рассматривать как указатели. Единственное отличие состоит в том, что вы не можете изменить место, на которое указывает ссылка, после того, как она была назначена. В вашем операторе присваивания вы копируете содержимое ссылок, а не назначаете место, на которое указывает ссылка.
Для компилятора следующие классы эквивалентны, обратите внимание, что версия указателя разыменовывает указатели для копирования содержимого:
class A_Ref{
public:
A_Ref(U& u):u_(u){}
A_Ref& operator=(const A_Ref& a){
u_ = a.u_;
return *this;
}
U& u_;
};
class A_Ptr{
public:
A_Ptr(U* u):u_(u){}
A_Ptr& operator=(const A_Ptr& a){
*u_ = *a.u_;
return *this;
}
U* u_;
};
Вам даже не нужно делать оператор присваивания частным, так как компилятор будет знать, что его не нужно генерировать, если есть константный член или ссылка. Они не могут быть переназначены.