当前位置:网站首页>C-默认构造函数什么情况下才真正被合成
C-默认构造函数什么情况下才真正被合成
2022-08-08 06:20:00 【亓逸】
C++ 默认构造函数什么情况下才真正被合成
前提知识:C++ 默认构造函数为什么存在以及编译器怎么实现
对于class X,如果没有任何user-declared constructor,那么就会有一个default constructor被隐式(implicitly)声明出来······ 一个被隐式声明出来的default constructor将是一个trivial(浅薄而无能,没啥用的)constructor······ ——摘自《深度探索C++对象模型》
首先需要解读上面这句话,在类设计的过程,类成员中没有提供一个用户自定义的构造函数,编译器会隐式声明一个默认构造函数给类。但是这个默认构造函数中做了什么?是否对类的构造有作用?
这是笔者一开始学习该知识过程中所不具备的知识。
什么是nontrivial constructor?
如果一个class没有任何constructor,但它内涵一个member object,而后者有default constructor,那么这个class的implicit constructor就是"nontrivial(有用的)"
编译器需要为该class合成一个default constructor。不过这个合成操作只有在constructor 真正需要被调用时才会发生
“带有Default Constructor” 的 Member Class Object
举个例子,在下面的程序片段中,编译器为 class Bar 合成一个 default construction:
class Foo { public: Foo(), Foo(int) };
class Bar { public: Foo foo; char* str; };
void foo_bar()
{
Bar bar; // Bar::foo 必须在此处初始化
if ( str ) { } ...
}
被合成的Bar default constructor 内含必要的代码,能够调用class Foo 的 default constructor 来处理member object Bar::foo,但它并不产生任何代码来初始化Bar::str。因为在开发者角度上出发,Bar::foo初始化是编译器的责任,将Bar::str初始化则是程序员的责任。被合成的default constructor 看起来可能是这样的
inline
Bar::Bar()
{
foo.Foo::Foo();
}
但在程序员定义的default constructor中
Bar::Bar() { str = 0; }
现在程序员的需求的满足了,但是编译器还需要初始化member object foo,由于default constructor 已经被现实定义出来,编译器无法合成第二个。
那么这个时候编译器的行动是
如果class A内含一个或一个以上的member class objec,那么class A的每一个constructor 必须调用每一个member classes的default constructor
延续上诉的例子,扩张后的constructor可能是这样的
Bar::Bar()
{
foo.Foo::Foo();
str = 0;
}
多个member class object,则按照声明顺序,按序初始化
Bar::Bar()
{
foo.Foo::Foo();
foo1.Foo:Foo();
foo2.Foo::Foo();
str = 0;
}
“带有Default Constructor” 的 Base Class
与上述道理相似。
如果一个没有任何constructors的class派生自一个"带有default constructor" 的 base class,那么这个derived class 的default constructor 会被视为nontrivial,并因此需要被合成出来。它将调用上一层base classes的default constructor(根据它的声明顺序)。对一个后继派生的class而言,这个合成的constructor 和 一个"被显示提供的default constructor" 没有什么差异
“带有一个Virtual Function” 的 Class
另外有两种情况,也需要合成default constructor:
- class声明(或继承)一个virtual function
- class派生自一个继承串链,其中有一个或更多的virtual base classes
如"带有一个Virtual Function" 的 Class这一前提
有两个扩张的行为会在编译期间发生:
- 一个virtual function table会被编译器产生出来,内放class的virtual function地址
- 在每一个class object中,一个额外的pointer member(也就是vptr)会被编译器合成出来,内含相关之class vtbl的地址
故对于那些未声明任何constructions的classes,编译器会为它们合成一个default constructor,以便正确地初始化每一个class object的vptr
“带有一个Virtual Base Class” 的 Class
前提:菱形继承所涉及到的虚继承
class X { public : int i; };
class A : public virtual X { public : int j; }
class B : public virtual X { public : double d; }
class C : public A, public B { public : int k; }
//无法再编译期决定 pa->x::i 的位置
void foo( const A* pa ) { pa->i = 1024; }
操作需要在运行期才得以确认,为了符合这样的实现策略
//可能的编译器转变操作
void foo( const A* pa ) { pa->_vbcx->i = 1024; }
其中_vbcx表示编译器所产生的指针,指向virtual base class X
总结
在上述4种情况下的class 中没有声明constructor的时候,由于缺乏user声明的constructions,编译器都会生成一个nontrivial constructor,将详细记录合成一个default cons的必要信息。
所以C++ 新手一般有两个常见的误解:
- 任何class如果没有定义default constructor,就会被合成出一个来。
- 编译器合成出来的default constructor 会显式设定”class 内每一个data member的默认值
没有一个是真的!
边栏推荐
- np.iinfo和 np.finfo的用法
- Web Application Vulnerability Assessment with Zap and W3af
- Day7:面试必考选择题
- convolutional neural network image recognition, convolutional neural network image processing
- 人机对话中得意图识别(关键词提取,svm工具)
- redis客户端Jedis/Redisson/Letture对比示例代码
- 机器学习,信用卡项目(二分类问题)完整代码 + 详细注释
- 2021 mathematical modeling national competition question B
- Synchronization and Asynchrony of Clocks
- 使用XGboost进行分类,判断该患者是否患有糖尿病
猜你喜欢

信息传输率(Information Translate Rate,ITR)

Promise的使用与async/await的使用

李沐老师 PyTorch版——线性回归 + softmax回归的简洁实现(3)

KDD'22 Recommendation System Papers (24 Research & 36 Application Papers)

APISIX Ingress v1.5-rc1 发布

Horizontal version of the generated image uniapp H5 signature

stack-queue

Pit Filling Simulated Hash Table

flex布局缺点

卷积神经网络 图像识别,卷积神经网络 图像处理
随机推荐
leetcode 232. Implement Queue using Stacks 用栈实现队列(简单)
State Compression Review
C人脸识别
torch.gather() 用法解读
webstorage
Rust学习:5_所有权与借用
ffmpeg获取视频时长和分辨率
Test and Debug
机器学习之R语言caret包trainControl函数详解
ValueError: Length of feature_names, 4 does not match number of features, 2 的解决方法
李沐老师 PyTorch版——线性回归 + softmax回归的简洁实现(3)
File Operations - IO
Basic tools - NETCAT (Telnet - banner, transfer text message)
逻辑回归 判断学生能否被大学录取
卷积神经网络的基本操作,卷积神经网络卷积计算
卷积神经网络 图像识别,卷积神经网络 图像处理
flex布局属性简约速记
don't know what to name
The pta patching simple graph theory
网络安全:系统文件属性