目录
1、成员变量变化时,不要忘记拷贝构造和赋值重载
2.继承时不要忘记基类的对象
3.拷贝构造和赋值重载不要相互调用
1、成员变量变化时,不要忘记拷贝构造和赋值重载
好的面相对象的系统会将内部封装,只留下赋值重载,和拷贝构造对 对象进行拷贝。
class custorm
{
public:
custorm(const custorm & c)
:_name(c._name)
{
cout << "custorm(const custorm & c)" << endl;
}
custorm &operator=(const custorm &c)
{
cout << "custorm &operator=(const custorm &c)" << endl;
_name = c._name;
return *this;
}
private:
string _name;
};
当拷贝构造,赋值重载被调用时,会打印对应的信息。这时候一切都很都好。
直到Date的到来。
class custorm
{
public:
custorm(const custorm & c)
:_name(c._name)
{
cout << "custorm(const custorm & c)" << endl;
}
custorm &operator=(const custorm &c)
{
cout << "custorm &operator=(const custorm &c)" << endl;
_name = c._name;
return *this;
}
private:
string _name;
Date _birthday;
};
这时候不要忘记修改拷贝构造和赋值重载,因为编译器不会对这种行为,发生任何的警告,但是拷贝构造和赋值重载已经是局部拷贝了。
2.继承时不要忘记基类的对象
相比上面,继承的时候才是最容易出问题的。
class PriorityCustorm : public custorm
{
public:
PriorityCustorm()
{}
PriorityCustorm(const PriorityCustorm &pc)
:_priority(pc._priority)
{}
PriorityCustorm& operator=(const PriorityCustorm & pc)
{
_priority = pc._priority;
return *this;
}
private:
int _priority;
};
上述代码表面看着没啥问题,其实问题大了
直接把基类的对象给完全忘记了
拷贝构造:这个时候基类对象会自己调用没有实参的默认构造(没有默认构造编译不过)。
赋值重载:基类的部分会不变。
这才是正确的代码。
class PriorityCustorm : public custorm
{
public:
PriorityCustorm()
{}
PriorityCustorm(const PriorityCustorm &pc)
:custorm(pc)
,_priority(pc._priority)
{}
PriorityCustorm& operator=(const PriorityCustorm & pc)
{
operator=(pc);
_priority = pc._priority;
return *this;
}
private:
int _priority;
};
3.拷贝构造和赋值重载不要相互调用
这两个东西的语法意义就是完全不同的。
拷贝构造:构造一个未初始化的对象。
赋值:对一个已经存在的对象进行赋值。
拷贝构造调用赋值就是对一个未初始化的对象进行赋值。
赋值调用拷贝构造就是对一个构造一个已经初始化对象。
狗屁不通,千万别这么用。
如果拷贝构造和赋值重载有重复的代码,就把共同的部分抽离的到一个函数中,调用这个函数就好了,把这个函数写成init和private的。