Default Constructor的构造操作
Default Constructor的构造操作
C++ Annotated Reference Manual书中的Section 12.1说过:default constructor 只有在编译器需要的时候才会被编译器合成出来。
C++ Standard修改了C++ ARM的说法,但实际上的行为是一样的。C++ Standard[ISO-C++95]的Section 12.1说到:对于class X,如果没有任何user-declared constructor,那么会有一个default constructor被隐式(implicitly)声明出来。不过这样的隐式声明的default constructor将是一个trivial(无用的)constructor。也就是所谓的implicit trivial default constructor,它们实际上并不会被合成出来。
那到底声明才是C++ ARM所说的编译器需要的情况呢?
第一,“带有Default Constructor”的Member Class Object
如果一个class X没有任何constructor,但它有至少一个member object,而这个member object对应的class有default constructor,那么编译器就需要为class X合成一个default constructor。不过这个合成操作只有在constructor被调用的时候才会发生。
举个例子:
class Foo { public : Foo(), Foo(int)…};
class Bar {pubcli Foo foo; char *str;};
void foo_bar()
{
Bar bar; // Bar:foo 必须在此处初始化。
}
被合成的default constructor看起来可能像这样(省略this指针):
inline
Bar::bar()
{
foo.Foo::Foo();
}
第二,“带有Default Constructor”的Base Class
与第一点类似,如果一个没有任何constructor的class派生自一个“带有Default Constructor”的base class,那么编译器会为这个derived class合成一个default constructor,它将调用上一层base classes的default constructor(根据它们声明顺序)。如果同时存在第一点和第二点的情况,则member class objects constructor会在所有base class constructor之后再调用。
第三,“带有至少一个Virtual Function”的Class
编译器会为每一个“带有至少一个Virtual Function”的class object的vptr(指向virtual table)设定初值。对于一个没有任何constructor的class,编译器会为它合成一个default constructor,以便正确地初始化每一个class object的vptr。
第四,“带有至少一个Virtual Base Class”的Class
Virtual base class的实现法在不同的编译器之间有极大地差异。然而,每一种实现法的共同点在于必须使virtual base class在其每一个derived class object中的位置,能够于执行期准备妥当。
举个例子:
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;}
main()
{
foo(new A);
foo(new B);
}
编译器无法固定住foo()之中“经由pa而存取的X::i”的实际偏移位置,因为pa的真正类型可以改变。编译器必须改变“执行存取操作”的那些代码,使X::i可以延迟至执行期才决定下来。
对于一个没有任何constructor的class,编译器会为它合成一个default constructor,在这个default constructor中会安插那些“允许每一个virtual base class的执行期存取操作”的代码。
总结,在以上4种情况,“编译器必须为未声明constructor的classes合成一个default constructor”。C++ Standard把那些合成物称为implicit nontrivial default constructor。被合成出来的constructor只能满足编译器(而非程序)的需要。它之所以能够完成任务,是借着“调用member object或base class的default constructor”或是“为每一个object初始化其virtual function机制或virtual base class机制”而完成的。至于不存在那4中情况而又没有声明任何constructor的classes,我们说它拥有的是implicit trivial default constructor,它们实际上并不会被合成出来。
注意:
1、在合成的default constructor中,只有base class subobjects和member class objects会被初始化。所有其他的nonstatic data member(如整数,整数指针,整数数组等等)都不会被初始化。这些初始化操作对于编译器都是非必要的,提供这些初始化操作的应该是程序员而不是编译器。
2、不是任何没有定义default constructor的class都会生成一个implicit default constructor。
3、编译器合成的default constructor不会显示设定“class 内每一个data member的默认值”。
Default Constructor的构造操作的更多相关文章
- 深度探索C++对象模型之第二章:构造函数语意学之Default constructor的构造操作
C++新手一般由两个常见的误解: 如果任何class没有定义默认构造函数(default constructor),编译器就会合成一个来. 编译器合成的的default constructor会显示的 ...
- Copy Constructor的构造操作
Copy Constructor的构造操作 有三种情况,会以一个object的内容作为另一个class object的初值: 1. 对一个object做显式的初始化操作 class X{…}; X ...
- C++对象模型——Default Constructor的建构操作(第二章)
第2章 构造函数语意学 (The Semantics of Constructor) 关于C++,最常听到的一个抱怨就是,编译器背着程序猿做了太多事情.Conversion运算符就是最常被引用的 ...
- 深度探索C++对象模型之第二章:构造函数语意学之Copy constructor的构造操作
C++ Standard将copy constructor分为trivial 和nontrivial两种:只有nontrivial的实例才会被合成于程序之中.决定一个copy constructor是 ...
- 构造函数语义学——Copy Constructor 的构造操作
前言 在三种情况下,会以一个 object 的内容作为另一个 class object 的初值: object明确初始化 class X{...}; X x; X xx = x; object 被当作 ...
- 构造函数语义学之Default Constructor构建操作
一.Default Constructor的构建操作 首先大家要走出两个误区: 1).任何class如果没有定义default constructor,就会被合成一个来. 2).便以其合成出来的def ...
- C++对象模型(一):The Semantics of Constructors The Default Constructor (默认构造函数什么时候会被创建出来)
本文是 Inside The C++ Object Model, Chapter 2的部分读书笔记. C++ Annotated Reference Manual中明确告诉我们: default co ...
- Error:Error: Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]
原文博客链接:https://blog.csdn.net/chniccs/article/details/51258972 在创建fragment时,你可能在打包时碰到如下错误 Error:Error ...
- 构造函数语义学——Default Constructor篇
构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...
随机推荐
- Android数据库--Sqlcipher的使用(一)
1.下载官方支持包:https://s3.amazonaws.com/sqlcipher/3.2.0/sqlcipher-for-android-community-v3.2.0.zip Github ...
- H5移动端页面设计心得分享(转载)
去年JDC出了不少优秀的武媚娘…不,H5呢,大家都很拼,同时当然也积累了一些经验和教训,今天结合咱们的实战案例,从字体,排版,动效,音效,适配性,想法这几个方面好好聊一聊关于H5的设计,希望对同学们有 ...
- NYOJ-914 Youth的最大化(贪心)
Youth的最大化 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗? ...
- readline与readlines不能同时使用
fd = open("C:\Users\william\Desktop\dup_file - Copy (2).txt")for i in xrange(0,len(fd.read ...
- django urls.py更改遇到问题
Q:TypeError: view must be a callable or a list/tuple in the case of include() A:django 1.10版本改了写法了.首 ...
- 在Table的Tbody中实现滚动条滚动
功能描述: 在一个Table中实现表头固定不动,内容部分实现通过滚动条滚动. 实现效果: 当页面宽度变宽时,只有最后一列的宽度会改变. 逻辑实现: 1.将表头和内容分别使用两个table标签包裹,每一 ...
- power oj 1557种树[二进制状压DP]
题目链接[https://www.oj.swust.edu.cn/problem/show/1557] 题意:中文题目. 题解:用0,1表示某个位置是否种了树,先算出同一行的有效状态的总数,即开两个1 ...
- date,datetime,timestamp 的区别
date 表示年月日,如YY-MM-DD datetime 表示年月日和时间信息,如YY-MM-DD HH:MM:SS datestamp 和datetime表示的信息相同,但时间范围不同 时间范围 ...
- save-dev和save的区别
果你经常用NPM安装依赖包,会注意到安装包时的指令会分--save-dev和--save两种,有什么区别呢? 在项目中我们通常会有一个package.json的配置文件,用来保存项目的相关配置信息 ...
- 纯 CSS 实现三角形尖角箭头的实例
上次无意中发现了个使用纯 CSS 实现三角形尖角箭头的方法 http://blog.csdn.net/zhouzme/article/details/18901943 ,但没有怎么用上,也没有详细完整 ...