1. 赋值操作的结合顺序
赋值操作的结合顺序是从右到左,即
a = b = c;
a = (b = c);
2. 输入参数一般为 const classname &
加 const 是因为:
- 不希望对用于赋值的“原版”做改动
- 加 const,对于 const 和 nonconst 的实参,函数都可以接受;若不加,则只能接受 nonconst 型的实参
加引用是因为:
- 提高效率,避免了函数调用时对实参的一次拷贝
3. 函数返回类型一般为 classname &,返回当前值 (return *this; )
原因是:
- 提高效率,避免了一次拷贝
- 可以实现连续赋值,例如:
(a = b) = c;
若返回值类型而非引用,则 (a = b) 之后为一匿名对象,而该匿名对象为右值,然后将 c 赋值给该匿名对象,程序报错(无法赋值给右值)
4. 默认赋值构造函数
当程序没有显式地提供一个以 类类型 或 类的引用类型 为参数的赋值构造函数时,编译器会提供一个默认的赋值构造函数 (程序提供了一个赋值构造函数,但参数非类类型或非类的引用类型时,编译器也可能会提供默认的赋值构造函数)
5. 赋值操作调用拷贝构造函数
当使用一个非类类型的值为类类型对象进行赋值时:
- 若匹配的赋值构造函数和拷贝构造函数同时存在,则调用赋值构造函数
- 若只有匹配的拷贝构造函数存在,则调用拷贝构造函数
6. 赋值构造函数只能是类的非静态成员函数
不能是静态成员函数,是因为:
- 静态成员函数只能操作类的静态成员,不能操作非静态成员。
如果我们将赋值运算符重载函数定义为静态成员函数,那么,该函数将无法操作类的非静态成员,这显然是不可行的。
不能是友元函数,是因为:
- 当程序没有显式地提供一个以类类型或类的引用类型为参数的赋值运算符重载函数时,编译器会自动提供一个。
现在,假设C++允许将赋值运算符重载函数定义为友元函数并且我们也确实这么做了,而且以类的引用为参数。与此同时,我们在类内却没有显式提供一个以本类或本类的引用为参数的赋值运算符重载函数。
由于友元函数并不属于这个类,所以,此时编译器一看,类内并没有一个以本类或本类的引用为参数的赋值运算符重载函数,所以会自动提供一个。
此时,我们再执行类似于str2=str1这样的代码,那么,编译器是该执行它提供的默认版本呢,还是执行我们定义的友元函数版本呢?
为了避免这样的二义性,C++强制规定,赋值运算符重载函数只能定义为类的成员函数,这样,编译器就能够判定是否要提供默认版本了,也不会再出现二义性。
7. 赋值构造函数不能被继承
为什么不能被继承呢?
- 因为相较于基类,派生类往往要添加一些自己的数据成员和成员函数,如果允许派生类继承基类的赋值运算符重载函数,那么,在派生类不提供自己的赋值运算符重载函数时,就只能调用基类的,但基类版本只能处理基类的数据成员,在这种情况下,派生类自己的数据成员怎么办?
所以,C++规定,赋值运算符重载函数不能被继承
8. 赋值构造函数处理自赋值
证同测试
if (this == &rhs) return *this;
网友评论