C++编译器为空类“润物细无声”地做些什么

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++规则的前提下。做雷锋还要遵守规则,嗯。


你可能感兴趣的:(C++编译器为空类“润物细无声”地做些什么)