构造、析构、赋值运算
一、C++默默编写并调用了哪些函数
当你写下:
class CEmpty
{
}
这就好像你写下
class CEmpty
{
public:
CEmpty(){…}
CEmpty(const CEmpty &rhs){…}
~CEmpty(){…}
CEmpty& operator=(const CEmpty &rhs){…}
}
这些C++默默编写的函数只有在被调用时才会被编译器创建(默认都是public),这里的拷贝
都是浅拷贝。如果你定义了构造函数,C++就不会为类创建一个默认构造函数(无参构造函数)。
如果你的泪没有申明copy构造函数,也没申明copy assignment操作符,编译器也会为它
创建那些函数(如果它们被调用的话)。但是如果你的class里面内含const成员或者reference
成员,C++会拒绝编译那一行赋值操作,因为C++不允许让reference该指向不同的对象,更改
const成员也是不合法的,此时你必须定义自己的copy assignment操作符。还有一种情况,如果
某个base classes 将copy assignment申明为private,编译器会拒绝为其derived classes生成一个
copy assignment(这个涉及到C++语言的对赋值的内部处理).
二、如不想使用编译器自动生成的函数,就该明确的拒绝
1、可以将构造、赋值操作符等申明为私有函数即可,不必实现。
这个还不是绝对安全,因为member函数和friend函数还是可以调用的。
不去定义它们的话,不慎调用它们就会获得一个连接错误。
2、设计一个专门为了阻止copying动作的base class
例如
class Cuncopyable
{
public:
Cuncopyable(){};
~Cuncopyable(){};
private:
Cuncopyable(cosnt Cuncopyable &);
Cuncopyable& operator=(const Cuncopyable &);
}
class A:private Cuncopyable
{
…
}
前面说了,这样就不会为derived class产生相应默认函数了
三、为多态基类申明virtual析构函数
class A{...};
class B:public A
{...};
A *p = new B;
delte p;
如果class A(基类)不含虚析构函数,A*类型的指针指向派生类B的对象,当delete p时就不会
调用B(派生类)的析构函数,实际执行时通常发生的是派生类的成分没有被销毁。类中有虚函
数时会产生一个虚指针占用一定内存空间。
所以,带多态性质的基类应该申明一个virtual析构函数,如果class带有任何virtual函数,他就应该有个析构函数。
classes的设计目的如果不是为了作为基类使用,或不是为了具备多态性,就不该申明虚析构函数。string和所有
的STL容器都不带虚析构函数。