C++内嵌对象,初始化列表和默认构造函数详解

#C++内嵌对象

##内嵌对象定义
数据域是一个对象类型
很显然如果一个类的数据域是一个对象类型,那么在这个类构造之前必须先构造内嵌对象。
由此就引出了初始化列表,默认构造函数的概念与意义
下面我们用一个统一的例子分别介绍这两个概念

#include <iostream>
#include <typeinfo>
#include <array>
using namespace std;
class Circle{
private:
    double radius;
public:
    Circle() = default;
    Circle(double radius){
        this->radius = radius;
    }
};
class Square{
private:
    double side;
public:
    Square() = delete;
    Square(double side): side{side}{}

};
class Combo{
public:
    Combo() {}
private:
    Circle c;
    Square s;

};
int main()
{
    //Combo o;
    array<int,3> a1 {1,2,3};

}

#默认构造函数

##默认构造函数定义
默认构造函数是一个可以无参调用的构造函数。
注意:
无参调用并不意味着默认构造函数一定是没有参数的:
默认构造函数既可以定义为空参数列表的构造函数,也可以是所有参数都有默认参数值的构造函数。

默认构造函数我们可以自己定义:

Circle() {}

当类中没有构造函数的时候编译器会给我们自动分配一个默认构造函数
当类中存在其他类型的构造函数时则不会分配。
C++中有两个语句可以命令编译器生成或者不生成默认构造函数

Circle() = default;//生成默认构造函数
Circle() = delete;//不生成默认构造函数

##默认构造函数与内嵌对象
前面提到内嵌对象必须在被嵌对象之前初始化也就是在调用被嵌对象的构造函数之前内嵌对象已经调用过构造函数。
现在我们观察文章最开始的例子:
Combo类中有两个内嵌对象Square类型的s和Circle类型的c

class Combo{
public:
    Combo() {}
private:
    Circle c;
    Square s;

};

在C++11中类的C++11非静态成员可以在声明的时候初始化
如果Circle类和Square类中存在默认构造函数那么此处c,s两个内嵌对象就已经被初始化完成。
这样我们在主函数中

Combo c;

是不会报错的

#初始化列表

现在我们看开头的例子

class Square{
private:
    double side;
public:
    Square() = delete;
    Square(double side): side{side}{}

};

我们看到Square类中我们强制的命令编译器不生成默认构造函数
这样Square类中只有有参构造函数,Combo中就不能运用就地初始化来定义Square s

class Combo{
public:
    Combo() {}
private:
    Circle c;
    Square s;

};

这样就不满足内嵌对象的要求,在主函数中初始化Combo编译器会报错
这样除了让编译器生成默认构造函数之外我们还可以利用初始化列表的方式解决这个问题:

class Combo{
public:
    Combo():s(1.0}) {}
private:
    Circle c;
    Square s;

};

初始化列表的位置在构造函数函数体的前面这样就满足了内嵌对象的要求
初始化列表也可以定义不同变量,但显然它真正的意义是对于内嵌对象的定义

#总结

C++的初始化方式众多,非常复杂上面所列举的为了实现内嵌对象而出现的初始化列表也只不过是为程序员减负而已。

相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页