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的构造操作的更多相关文章

  1. 深度探索C++对象模型之第二章:构造函数语意学之Default constructor的构造操作

    C++新手一般由两个常见的误解: 如果任何class没有定义默认构造函数(default constructor),编译器就会合成一个来. 编译器合成的的default constructor会显示的 ...

  2. Copy Constructor的构造操作

    Copy Constructor的构造操作 有三种情况,会以一个object的内容作为另一个class object的初值: 1.  对一个object做显式的初始化操作 class X{…}; X ...

  3. C++对象模型——Default Constructor的建构操作(第二章)

    第2章    构造函数语意学 (The Semantics of Constructor) 关于C++,最常听到的一个抱怨就是,编译器背着程序猿做了太多事情.Conversion运算符就是最常被引用的 ...

  4. 深度探索C++对象模型之第二章:构造函数语意学之Copy constructor的构造操作

    C++ Standard将copy constructor分为trivial 和nontrivial两种:只有nontrivial的实例才会被合成于程序之中.决定一个copy constructor是 ...

  5. 构造函数语义学——Copy Constructor 的构造操作

    前言 在三种情况下,会以一个 object 的内容作为另一个 class object 的初值: object明确初始化 class X{...}; X x; X xx = x; object 被当作 ...

  6. 构造函数语义学之Default Constructor构建操作

    一.Default Constructor的构建操作 首先大家要走出两个误区: 1).任何class如果没有定义default constructor,就会被合成一个来. 2).便以其合成出来的def ...

  7. C++对象模型(一):The Semantics of Constructors The Default Constructor (默认构造函数什么时候会被创建出来)

    本文是 Inside The C++ Object Model, Chapter 2的部分读书笔记. C++ Annotated Reference Manual中明确告诉我们: default co ...

  8. 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 ...

  9. 构造函数语义学——Default Constructor篇

    构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...

随机推荐

  1. Openjudge-NOI题库-字符串移位包含问题

    题目描述 Description 对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串. 给定两个字符串s1和s2,要求判定其中一个字符串是否是另一字符串通过若干次 ...

  2. mob.com Android studio 配置环境

  3. swift label不同颜色、不同字体

    let string = "点击注册按钮,即表示您已同意隐私条款和服务协议" let ranStr = "同意" let attrstring:NSMutabl ...

  4. delphi 快捷键大全

    ************************* 1.功能键 2.组合键 3.其他快捷键 4.补充 5.补充1(带分类) 6.补充2 --Edit by 2013.1.14 ************ ...

  5. chrome devtools

    Elements chrome devtools 中 Elements panel 是审查 dom 元素和 css 的, 可以实时修改 dom/css. windows: ctrl + shift + ...

  6. django 安装记录

    1. 下载django安装包,下载个最新的安装包即可. https://www.djangoproject.com/download/ 2. 在本地解压   tar -xvf  安装包名称 3. 安装 ...

  7. 【Python之路】第四篇--Python基础之函数

    三元运算 三元运算(三目运算),是对简单的条件语句的缩写 # 书写格式 result = 值1 if 条件 else 值2 # 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2” ...

  8. 解决maven web项目Cannot detect Web Project version. Please specify version of Web Project through...的错误

    前面已经创建maven web工程,但是问题来了,创建maven web工程之后会出现如下的错误,在pom.xml文件头部 有以下的错误 Description Resource Path Locat ...

  9. WEB 技术分类 Javascript DOM(Element Node) BOM

    Web technology for developers   Web 技术文档 备注:本文介绍web technology的分类,各自职责,因为之前一直就没有搞明白各种技术.各种名词究竟是属于哪个范 ...

  10. Android Studio 中提示 Private field 'mType' is assigned but never accessed 的原因

    Android Studio 是个很酷的编译器,之前发现有个代码提示很奇怪,但无奈一直没看懂他的意思,不过也没报错就没太在意,刚刚突然领悟了,原来是自己代码不规范. Private field 'mT ...