Step1:写个空类
class CBlueSky{};
注:sizeof(CBlueSky) 等于 1
Step2:编译器可能会为CBlueSky空类声明以下函数/操作符:如果默认构造函数,拷贝构造函数,析构函数,赋值操作符,如下所示:
class CBlueSky{
public:
CBlueSky() { ...} // 默认构造函数
CBlueSky(const CBlueSky& other) {...} //拷贝构造函数
~CBlueSky(){...} //析构函数
CBlueSky& operator = (const CBlueSky& other) {...} //拷贝赋值操作符
};
注:这些函数都是pubic且inline函数!
注:sizeof(CBlueSky) 等于 1,抛个问题:思考下类的size问题。
Step3:上面的“可能会“如何理解?
当这些函数被需要时,在编译阶段会被编译器声明创建出来。被需要的示例如下所示:
CBlueSky a1; //需要 默认构造函数
//声明周期结束时,需要 析构函数
CBlueSky a2(a1); //需要 拷贝构造函数
a2 = a1; //需要 拷贝赋值操作符
如果这时候你的CBlueSky是空类,则编译器会声明以上这些函数。
如果这时候你的CBluseSky已经实现了这些函数,编译器只进行编译操作,不会再声明这些函数。
Step4:如果CBlueSky类如果定义了构造函数,编译器不会再为CBlueSky声明创建任何构造函数。
//< BlueSky.h #ifndef __BLUESKYJOYN_BLUESKY_H_ #define __BLUESKYJOYN_BLUESKY_H_ namespace BlueSkyJoyn { class CBlueSky { public: CBlueSky(int age); private: int m_age; }; } #endif
//< BlueSky.cpp #include "BlueSky.h" namespace BlueSkyJoyn { CBlueSky::CBlueSky(int age):m_age(age) {} } int main() { BlueSkyJoyn::CBlueSky a1; return 0; }
main中的a1需要调用无参默认构造函数,但是CBlueSky已经有了构造函数(但没有默认构造函数),编译器不会再为CBlueSky创建无参默认构造函数,而是提示error,编译失败。
Step5:没有拷贝赋值操作符,编译器给你声明创建,看下例:
上面main换成下面,可以通过编译
int main()
{
//BlueSkyJoyn::CBlueSky a1;
BlueSkyJoyn::CBlueSky a1(25);
BlueSkyJoyn::CBlueSky a2 = a1; //调用copy assignment操作符,没有声明定义,编译器为你声明创建
return 0;
}
注:由于没有调用到拷贝构造函数,编译器不会为你声明创建copy constructor。
Step6:编译器不会随意给你创建copy constructor,他也要遵守C++规则。
C++规则,先看一个,如下所示:
1)引用初始化后不允许 指向其他不同的对象,如:
int i = 1;
int j = 2;
int &ri = i;
ri = j; // wrong!!!!, C++不允许让ri指向其他int对象
由上可知,如果CBlueSky类中有reference成员时,编译器为了遵守C++的“reference对象 不允许指向其他对象”规则,不会为其生命创建拷贝赋值操作符!
2)如果类中有"内含const 成员,则编译器也会拒绝为其创建operator=操作符
3)如果base-class的operator=是private,则编译器拒绝为其derived-class声明创建operator=操作符
综上所述:编译器可以“润物细无声”地为一个类创建默认构造函数,拷贝构造函数,拷贝赋值操作符,析构函数,声明创建这些函数是在遵守C++规则的前提下。做雷锋还要遵守规则,嗯。