惠州做网站好的公司,光华路网站建设,谷城网站开发,wordpress单栏主题 极简1、“Default Constructor” 的构造操作
下面4种情况编译器会生成默认构造函数#xff1a;
成员类对象带有默认构造函数父类带有默认构造函数带有虚表的类带有虚基类的类
1.1、 成员类对象带有默认构造函数
如果一个类没有任何构造函数#xff0c;但它的一个成员对象带有…1、“Default Constructor” 的构造操作
下面4种情况编译器会生成默认构造函数
成员类对象带有默认构造函数父类带有默认构造函数带有虚表的类带有虚基类的类
1.1、 成员类对象带有默认构造函数
如果一个类没有任何构造函数但它的一个成员对象带有默认构造函数 那么编译器会在需要的时候为这个类生成默认构造函数。
举个例子下面的程序中编译器会为Bar生成一个默认构造。 class Foo
{
public:Foo(){}
};class Bar
{
public:Foo foo;int no;
};void foo_bar()
{Bar bar;//Bar::foo 在这里初始化...
}生成的构造函数看起来像下面这样
Bar::Bar()
{foo.Foo::Foo();
}如果class Bar提供了一个构造函数并初始化no像下面这样
Bar::Bar()
{no0;
}则编译器会将foo的构造安插到用户代码也就是no0的前面。像下面这样
Bar::Bar()
{foo.Foo::Foo();no0;
}如果类中有多个成员对象包含默认构造那么编译器则按照成员声明顺序依次插入成员对象的默认构造。
1.2 父类带有默认构造函数
类似的道理如果一个类没有定义任何构造函数而他的父类含有默认构造。编译器则在需要的时候给这个类生成一个默认构造用以调用父类的默认构造。
1.3、带有虚表的类
下面代码中class shape中定义了一个虚函数show()
class shape
{
public:virtual void show(){}
};下面两个扩展行动会在编译期产生
编译器生成一个虚函数表用于存放虚函数的地址一个指向虚函数表的指针会安插在 shape中
为此编译器会为shape生成一个默认构造用于设置vptr的值。
1.4、带有虚基类的类
与虚函数类似。如果一个类存在虚基类编译器会为生成一张虚基类表用以存放所有的虚基类会在类中安插一个虚基类表指针指向虚基类表。 如果这个类没有任何构造编译器则会生成一个默认构造用于正确设置虚基类表指针。
2、“Copy Constructor”的构造操作
下面4种情况编译器在需要的时候会生成拷贝构造
当类中含有一个成员对象而后者有一个拷贝构造当class继承一个父类而后者有一个拷贝构造类中声明了一个或多个虚函数有一个或多个虚基类
2.1、类中声明了一个或多个虚函数
下面代码定义了两个类Animal和Beer。
class Animal
{
public:virtual void draw(){...}
};class Beer :public Animal
{
public:void draw(){...}
};第一种情况
Beer a
Beer b a;因为a和b的vptr指向的是同一张虚函数表所以这里可以直接按位拷贝不需要生成拷贝构造。
第二种情况
Beer a
Animal b a;因为Beer和Animal拥有不同的虚函数表这里实行按位拷贝会有问题。这是编译器会为Animal生成拷贝构造用以正确的设置vptr。
2.2、有一个或多个虚基类
和带有虚函数的情况类似。如果相同类型之间的初始化使用按位拷贝就绰绰有余了。如果以派生类对象作为基类的初始值时或相反编译器会生成默认拷贝构造用以正确设置虚基类指针。
3、成员初始化列表
以下4种情况必须使用初始化列表
初始化一个引用成员时初始化一个const成员时调用父类构造而它拥有参数调用成员对象的构造而它拥有参数
初始化列表是按照成员声明的顺序执行的下面是一个常见的错误
class X
{
public:X(int val):j(val),i(j){}
private:int i;int j;
};X()中会先设置i的值由于这时 j 还是未定义的所以 i 被赋予了一个无效值。
转换后的X()像下面这样 X(int val)
{i j; //这里 j 还没有初始化。j val;...
}