电商网站建设方案100例,银行软件开发工资一般多少,动漫设计与制作实训报告,正规网站设计制作公司背景
作为一个C小白#xff0c;最近在看深度解析对象模型的时候#xff0c;发现一个很久以来的认知错误#xff1a;编译器会为没有定义构造函数的class生成一个默认构造函数。其实这个观点是错误的#xff0c;编译器只会在四种情况下生成。
相关知识
一定要明确一个事情…背景
作为一个C小白最近在看深度解析对象模型的时候发现一个很久以来的认知错误编译器会为没有定义构造函数的class生成一个默认构造函数。其实这个观点是错误的编译器只会在四种情况下生成。
相关知识
一定要明确一个事情就是基础数据类型没有默认构造函数因为int, float,char这些不是class/struct,基础数据类型就是基础数据类型不要自己强行脑补为类或者结构。构造函数花括号里不能用小括号初始化任何成员变量凡是想初始化都放在初始化列表里就好了
四种情况
情况一
当成员变量中有默认构造函数时举例说明
class Test
{
public:int a;float b;
};
int main()
{Test t;int c t.a 1;return 0;
}这种情况下编译器不会生成默认构造函数因为int, float不是对象没有默认构造函数。可以根据汇编代码发现确实没有。
class Test
{
public:int a;float b;string s;
};可以看到一旦加入string的话就会出现默认构造函数了。
情况二
该类的基类有默认构造函数
情况三
类中存在虚函数那么C编译器会为你生成默认构造函数以初始化虚表(虚函数表vftable)。
情况四
存在虚基类那么C编译器会为你生成默认构造函数以初始化虚基类表(vbtable)。
生成默认构造函数
首先生成一个空壳子
inline Construct()
{}补充初始化列表 这里是一个知识点list中的顺序是按声明顺序来的跟你怎么写代码没啥关系 这里初始化列表会把所有的成员变量的默认构造函数依次加入进来下面是一个伪代码的例子
class Test
{
public:float d;string A;Student B;Teacher C;int e;
}
inline Test() {A(), B(), C(), e} //这里e不会初始化只是分配内存
{}把初始化列表挪到函数大括号中
inline Test()
{A();B();C();e;
}**可以看到自动生成的默认构造函数其实并不会给所有成员都初始化**。此外这里可能会觉得第三步和第二步可以合在一起其实拆开是为了后面程序员自己添加构造函数时编译器补充函数信息逻辑更清楚。
自定义默认构造函数
对于自定义默认构造函数编译器有三个原则
插入的代码只能在用户实现的代码前补充的代码符合成员变量的声明顺序基础数据类型依然不是编译器的考虑的范围
方式一、初始化列表为空
我们根据上面已经知道编译器会自动生成构造函数但是如果程序员自己提供了构造函数怎么处理
class Test
{
public:float d;string A;Student B;Teacher C;int e;
}
Test()
Test::Test()
{B(student);
}补充初始化列表
Test()
Test::Test(){d, A(), B(), C(), e}
{//B(student); //编译器会报错成员变量**对象**(不是基础数据)必须在构造函数初始化列表里初始化B student;
}挪到函数中
Test()
Test::Test(){}
{d;A();B();C();e;B student;// 等效于tmp(student), Btmp;
}方式一、初始化列表不为空
class Test
{
public:float d;string A;Student B;Teacher C;int e;
}
Test()
Test::Test():B(student)
{
}补充初始化列表
Test()
Test::Test(){d, A(), B(student), C(), e}
{
}挪到函数中
Test()
Test::Test(){}
{d;A();B(student);C();e;
}根据这两个小例子可以好好的体会上面的三个原则