C++ 对象模型---构造函数篇

来源:互联网 发布:centos 6.5网卡安装 编辑:程序博客网 时间:2024/06/05 02:09

一. 默认构造函数

通常很多C++程序员存在两种误解:

  • 没有定义默认构造函数的类都会被编译器生成一个默认构造函数。
  • 编译器生成的默认构造函数会明确初始化类中每一个数据成员。

C++标准规定:如果类的设计者并未为类定义任何构造函数,那么会有一个默认 构造函数被暗中生成,而这个暗中生成的默认构造函数通常是不做什么事的(无用的),下面四种情况除外。

换句话说,有以下四种情况编译器必须为未声明构造函数的类生成一个会做点事的默认构造函数。我们会看到这些默认构造函数仅“忠于编译器”,而可能不会按照程序员的意愿程效命。

1.包含有带默认构造函数的对象成员的类

操作:调用成员类的默认构造函数

2.继承自带有默认构造函数的基类的类

操作:调用基类的默认构造函数

3.带有虚函数的类

操作:为类的每个构造函数添加代码来完成对vptr的初始化。

4.带有一个虚基类的类

操作:编译器要将虚基类在类中的位置准备妥当,提供支持虚基类的机 制。

总结:简单来讲编译器会为构造函数做的一点事就是调用其基类或成员对象的默认构造函数,以及初始化vprt以及准备虚基类的位置。

总的来说,编译器将对构造函数隐含操作的情况的流程分析(注意不是操作的流程):

1.如果类虚继承自基类,编译器将在所有构造函数中插入准备虚基类位置的代码和提供支持虚基类机制的代码。

2.如果类声明有虚函数,那么编译器将为之生成虚函数表以存储虚函数地址,并将虚函数指针(vptr)的初始化代码插入到类的所有构造函数中。

3.如果类的父类有默认构造函数,编译将会对所有的默认构造函数插入调用其父类必要的默认构造函数。必要是指设计者没有显示初始化其父类,调用顺序,依照其继承时声明顺序。

4.如果类包含带有默认构造函数的对象成员,那么编译器将会为所有的构造函数插入对这些对象成员的默认构造函数进行必要的调用代码,所谓必要是指类设计者设计的构造函数没有对对象成员进行显式初始化。成员对象默认构造函数的调用顺序,依照其声明顺序。

5.以上四种情况都是针对类显示定义了构造函数,而且是针对所有的构造函数进行代码插入,不仅仅是针对默认构造函数进行代码插入。若类没有定义任何构造函数,编译器会为其合成默认构造函数,再次执行上述四点。


需要说明的是,从概念来上来讲,每一个没有定义构造函数的类都会由编译器来合成一个默认构造函数,以使得可以定义一个该类的对象, 但是默认构造函数是否真的会被合成,将视是否有需要而定。C++ standard 将合成的默认构造函数分为 trivial 和 notrivial 两种,前文所述的四种情况对 应于notrivial默认构造函数,其它情况都属于trivial对于一个trivial默认 构造函数,编译器的态度是,既然它全无用处,干脆就不合成它。在这儿要厘清的是概念与实现的差别,概念上追求缜密完善,在实现上则追求效率,可以不要的东西就不要。


二. 拷贝构造函数

       强调:如果显示的定义了拷贝构造函数,则编译器对拷贝构造函数可能的代码插入操作见上节默认构造函数的前四条总结。如果没有定义拷贝构造函数,则请看下面总结:

   前提:用户没有显示定义拷贝构造函数

   从实现的角度讲,编译器对展现出bitwise copy semantics的类不会生成拷贝构造函数,而是按位逐次拷贝所有的对象的成员。

但是对于不展现bitwise copy semantics的类,编译器就要合成拷贝构造函数。注意:在被合成出来的拷贝构造函数中,如整数,指针,数组等等non class member也会被按位拷贝复制。在这一点上,拷贝构造函数和默认构造函数有不同。

不展现bitwise copy semantics的类分为四种情况:

  • 当类内含一个成员对象,而后者的类声明有一个拷贝构造函数时(不论是设计者定义的还是编译器合成的)。
  • 当类继承自一个声明有拷贝构造函数的类时(同样,不论这个拷贝构造函数 是被显示声明还是由编译器合成的)。
  • 类中声明有虚函数。
  • 当类的派生串链中包含有一个或多个虚基类。

   对于有虚函数的类,如果两个对象的类型相同那么位逐次拷贝其实是可以胜任的。 但问题将出现在,如果基类由其继承类进行初始化时,此时若按照位逐次拷贝来完成这个工作,那么基类的vptr将指向其继承类的虚函数表,这将导致无法预料的后果——调用一个错误的虚函数实体是无法避免的,轻则带来程序崩溃,更糟糕 的问题可能是这个错误被隐藏了。所以对于有虚函数的类编译器将会明确的使被初始化的对象的vptr指向正确的虚函数表。因此有虚函数的类没有声明拷贝构造 函数,编译将为之合成一个,来完成上述工作,以及初始化各数据成员,声明有拷贝构造函数的话也会被插入完成上述工作的代码。

   对于继承串链中有虚基类的情况,问题同样出现在继承类向基类提供初值的情况, 此时位逐次拷贝有可能破坏对象中虚基类子对象的位置。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 mac玩刺客信条卡怎么办 阴部长了个疙瘩怎么办 两个人觉得累了怎么办 朋友把我拉黑了怎么办 下雨了怎么办我好想你 雨停怎么办我好想你 下雨天怎么办我好想你 天谕账号忘记了怎么办 天谕账号被冻结怎么办 促黄体生成素低怎么办 地暖家里太干燥怎么办 剑灵摧毁了东西怎么办 想打嗝打不出来怎么办 孩子满100天要怎么办 宝宝吃奶粉过敏了怎么办 1岁宝宝不喝奶粉怎么办 母乳不够宝宝不喝奶粉怎么办 宝宝吃奶粉上火了怎么办 我小孩不喝奶粉怎么办 2岁宝宝不喝奶粉怎么办 婴儿吃奶粉上火了怎么办 100天的宝宝咳嗽怎么办 40天的小孩咳嗽怎么办 40天的婴儿咳嗽怎么办 50天的婴儿咳嗽怎么办 宝宝20天感冒了怎么办 1个月宝宝咳嗽怎么办 40天的宝宝干咳怎么办 百天的宝宝咳嗽怎么办 50天的孩子咳嗽怎么办 百天宝宝咳嗽有痰怎么办 1岁半宝宝拉肚子怎么办 百天的宝宝拉肚子怎么办 激战2帧数三十多怎么办 太受欢迎了怎么办txt微 太受欢迎了怎么办网盘 太受欢迎了怎么办微盘 我太受欢迎了该怎么办h 我太受欢迎了该怎么办1 卡培他滨副作用怎么办 究极风暴4卡怎么办