关于构造/拷贝构造;/析构/赋值函数
——什么情况下必须自己定义拷贝构造函数和重载赋值运算符?
若对象成员中有指针变量(其会指向动态分配的内存),则要自己声明拷贝构造函数和赋值运算符。
即使确定自己未来不会用到这两个函数,也最好声明出private的函数,空的。以防不小心被误用却还不报错。
——什么情况下使用构造函数的初始化列表?
应该尽量使用构造函数的初始化列表进行成员的初始化。尤其对于const类型成员和引用类型成员,必须用初始化列表。
对于对象成员,使用初始化列表来初始化能提高效率,只通过一次拷贝构造函数。如果在构造函数内部初始化的话,会先调用默认构造函数、然后再调用赋值运算符函数。
——什么情况下析构函数用virtual修饰?
如果一个类有virtual函数,那一定要让其析构函数也是virtual的。
这样,delete指向子类的父类指针时,不仅调用子类的析构函数,还调用父类的析构函数。
——怎么样重载赋值运算符?
hello& hello::operator=(const hello& rhs)
{
......
return *this;
}
其参数类型应该是const+引用。其返回值类型应该是引用。函数内部要返回this指针所指。
这样才能满足赋值时赋值传递的使用习惯。
——为什么有必要检查和避免自己赋值给自己?
因为对于动态分配的对象,有可能你在赋值时是先delete旧的,然后再new一个。这种情况下,如果是自己赋值给自己,就把赋值者也先删掉了,会出现危险的错误。
关于类和函数的设计
——怎么努力让类的接口完整且最小化?
一个class其实就是个type,跟内置类型一样,是给人用的。因此想让人用的舒服、用的放心,就要设计的简洁、通用、够用、并且不多余。比如设计一个数组的类模板,除了必须的构造、析构、拷贝构造、赋值之外,还要有数组下标访问运算符[ ],能得到数组边界begin/end,能取数组元素个数size。
PS:类模板vs模板类:
类模板class template ,是带有不确定数据类型的类。
模板类,是类模板的那些不确定的类型确定以后的类。