C++ 默认构造函数_SzMing的博客-程序员宝宝

一直认为若程序员没有自己定义无参数的构造函数,那么编译器会自动生成默认构造函数,来进行对成员函数的初始化,但这种认为是有误的,不全面的.

默认的构造函数分为有用的和无用的,所谓无用的默认构造函数就是一个空函数、什么操作也不做,而有用的默认构造函数是可以初始化成员的函数。

对构造函数的需求也是分为两类:一类是编辑器需求,一类是程序的需求。

程序的需求:若程序需求构造函数时,就是要程序员自定义构造函数来显示的初始化类的数据成员。

编辑器的需求:编辑器的需求也分为两类:一类是无用的空的构造函数,一类是编辑器自己合成的有用的构造函数。

在用户没有自定义构造函数的情况下:一、由于编辑器的需求,编辑器会调用空的无用的默认构造函数。二、但在下列情况下:编辑器就一定会合有用的默认构造函数。

看下面的例子:
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Foo   
  5. {  
  6. public:   
  7.     int val;   
  8.     Foo *pnext;   
  9. };   
  10.   
  11. void foo_bar()   
  12. {   
  13.     // Oops:  program needs bar's members zeroed out   
  14.     Foo bar;   
  15.     if ( bar.val || bar.pnext )   
  16.         cout << "Print the content !" << endl;   
  17. }   
  18.   
  19. int main()  
  20. {  
  21.     foo_bar();  
  22.     return 0;  
  23. }  

程序可以通过编译,但是显示:The variable 'bar' is being used without being initialized.

这就说明建立Foo bar; 这个对象编辑器并没有自动合成默认构造函数。

默认的构造函数也分为:有用的构造函数和无用的构造函数,所谓有用的构造函数就是构造函数会为我们的类做一些初始化的工作,而无用的构造函数对我们的类没有任何意义,我们常说的默认构造函数就是值有用的构造函数,英文为:nontrivial default constructor。

什么情况下编辑器才会自动合成有用的默认构造函数?(以下的默认构造函数均值有用的默认构造函数)

下面四种情况,编辑器才会背着用户自己合成默认构造函数:

一、带有“Default Constructor"的Member class Object.


如果一个类没有任何Constructor,但它内含一个带有Default Constructor的Member class Object。编辑器就会自动为此类合成一个默认的构造函数。

看下面的例子:
  1. #include<iostream>  
  2. using namespace std;  
  3.   
  4. class Foo   
  5. {   
  6. public:   
  7.     Foo();   
  8.     Foo( int );  
  9. private:  
  10.     int val;  
  11. };   
  12.   
  13. Foo::Foo()  
  14. {  
  15.   cout << "Call Foo::Foo() Constructor !"<< endl;  
  16.   val = 0;  
  17. }  
  18.   
  19. Foo::Foo(int i)  
  20. {  
  21.   cout << "Call Foo::Foo(int i) Constructor !"<< endl;  
  22.   val = i;  
  23. }  
  24.   
  25. class Bar   
  26. {   
  27. public:   
  28.     Foo foo;   
  29.     char *str;   
  30. };   
  31.   
  32. void foo_bar() {   
  33.     Bar bar; // Bar::foo must be initialized here   
  34.     if (bar.str )   
  35.     {  
  36.         cout << "Print the content !" << endl;  
  37.     }   
  38. }   
  39.   
  40.   
  41. int main()  
  42. {  
  43.     foo_bar();  
  44.     return 0;  
  45. }  

输出为:
Call Foo::Foo() Constructor !
Print the content !

类class Bar 没有自己定义的Constructor,而成员中的Foo foo; 却带有字定义的Constructor(Foo::Foo()),这种情况符合:"带有“Default Constructor"的Member class Object."

由输出结果可以看出:编辑器为class Bar合成了默认的构造函数,并调用了Foo的自定义构造函数。

那么编辑器为class Bar合成了默认的构造函数应该是什么样子呢?
  1. inline Bar::Bar()  
  2. {  
  3.  foo.Foo::Foo();  
  4. }  

编辑器会自动合成如上的默认构造函数。

如果一个类自定义了Constructor,但它内含一个带有Default Constructor的Member class Object。编辑器就会自动扩充此类的自定义构造函数。

如果类Bar自定义了构造函数,那么编辑器会怎么做,如下代码:
  1. class Bar   
  2. {   
  3. public:   
  4.     Bar();  
  5.     Foo foo;   
  6.     char *str;   
  7. };   
  8.   
  9. Bar::Bar()  
  10. {  
  11.     cout << "Call Bar::Bar() Constructor !"<< endl;  
  12.     str = 0;  
  13. }  

输出为:
Call Foo::Foo() Constructor !
Call Bar::Bar() Constructor !

看到输出结果仍然是调用了Foo的自定义的构造函数”Call Foo::Foo() Constructor !“。
那么这是如何做到的呢?

编辑器会扩充Bar自定义的构造函数,其结构如下:
  1. Bar::Bar()  
  2. {  
  3.  foo.Foo::Foo();  //这里是编辑器自动添加上去的  
  4.    cout << "Call Bar::Bar() Constructor !"<< endl;  
  5.   str = 0;  
  6. }  


二、如果派生列的基类中有自定义的nontrivial default constructor,那么编辑器会为每一个派生类合成一个nontrivial default constructor,以调用基类自定义的nontrivial default constructor。

三、如果一个类里隐式的含有Virtual tabel(Vtbl)或者pointer member(vptr)

vtbl或vptr需要编辑器隐式的合成出来,那么编辑器就把合成动作放在了默认构造函数里,所以编辑器必需自己产生一个构造函数来完成这些动作。

所以你的类里只要含有virtual function,那么编辑器就会生成默认的构造函数。

四、如果一个类虚继承与其他类

理由和上面一样,虚基类也需要vtbl和vptr管理,那么这些管理就需要合成构造函数来实现管理,则需要生成默认的构造函数。

所以类的基类有虚类,那么编辑器就会合成默认的构造函数。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/SzMinglove/article/details/8149422

智能推荐

CSDN超级实习生是指CSDN在招实习生吗?还是别的意思?_计算机考研的博客-程序员宝宝

近期多位用户反馈以为我们CSDN在招实习生,实际上CSDN也在招超级实习生,其他百度、阿里、腾讯都在招,超级实习生计划实习企业不限CSDN,达到用人标准可进各类互联网大厂,为了避免造成用户理解,下文小编将针对“CSDN超级实习生”做个简要介绍。

消息队列(MSMQ)学习_weixin_30715523的博客-程序员宝宝

直到今天才知道,在我们每天都在用的Window系统里还有这么好用的一个编程组件:消息队列.它能够解决在大数据量交换的情况下的性能问题,特别是BS系统的数据库性能.而且它的异步处理方式能给程序员最大的便利与最好的用户体验. 1.首先在需要进行消息队列的服务器上安装MSMQ,我的系统是win2003+iis6,所以这个安装选项在添加删除程序-&gt;windows组件-&gt;应用程序...

Navicat获取注册码_weixin_30767921的博客-程序员宝宝

产品适用:Navcat产品+中文版+64位注册机百度网盘链接: https://pan.baidu.com/s/1H49nNga9h0WHWKGWAGy18g 提取码: ri5d1、cmd进入注册机目录执行命令navicat-patcher.exe "D:\Program Files\PremiumSoft\Navicat Premium 12"(navicate的目录)2、执行...

HTML,CSS,font-family:中文字体的英文名称_F12578626的博客-程序员宝宝

宋体SimSun黑体SimHei微软雅黑Microsoft YaHei微软正黑体Microsoft JhengHei新宋体NSimSun新细明体PMingLiU细明体MingLiU标楷体DFKai-SB仿宋FangSong楷体KaiTi仿宋

随便推点

LuoguP2759奇怪的函数_hhuhao的博客-程序员宝宝_奇怪的函数 xx.cpp 数据

先来推一下: ∵log10xx>n−2∵log_{10}x^x>n-2 ∴x∗log10x>n−2∴x*log_{10}x>n-2 ∵x,log10x∵x,log_{10}x都是单调递增的 ∴x∗log10x∴x*log_{10}x是单调递增的

Windows界面编程第五篇 静态控件背景透明化_Fields_Of_Gold的博客-程序员宝宝

上一篇《Windows界面编程第三篇 异形窗体 普通版》和《Windows界面编程第四篇异形窗体 高富帅版》介绍了异形窗口(异形窗体)的创建,并总结出了异形窗口的“三要素”:1.WS_EX_LAYERED属性2.指定透明色3.以位图为窗口背景    本篇文章将主要介绍Windows编程中如何实现静态控件背景的透明化,这将进一步的美化界面。下面先看一张没有做静态控件背景透

lora终端连接云服务器_一种LoRa服务器及其数据传输方法与流程_weixin_39746382的博客-程序员宝宝

本发明涉及Lora技术领域:,尤其涉及一种LoRa服务器及其数据传输方法。背景技术::LoRaWAN是为LoRa远距离通信网络设计的一套通讯协议和系统架构。Lora通信系统通常包含终端、基站、网络服务器、应用服务器这四个部分。基站和终端之间采用星型网络拓扑,由于LoRa的长距离特性,它们之间得以使用单跳传输。终端节点可以同时发给多个基站,基站则对网络服务器和终端之间的LoRaWAN协议数据做转发处...

嵌入式系统学习-------1.什么是嵌入式系统?_迎着黎明那道光的博客-程序员宝宝_什么是嵌入式系统

什么是嵌入式系统?我们在日常的生活当中经常会听说到嵌入式应用,而在物联网的发展下,嵌入式的应用也变得更加多样起来,我们不禁会有一个疑问,什么是嵌入式系统,下面我们一起学习一下。嵌入式系统定义简单的讲,嵌入式系统就是嵌入到对象体中的专用计算机系统。它包含了嵌入、专用、计算机这三个要素。而广义的讲,嵌入式系统也就是具备某些功能的软硬件结合体。以应用为中心、以计算机技术为技术、软件硬件可裁剪、适...

idea创建maven项目中文乱码_代码搬运工呀的博客-程序员宝宝_idea maven乱码

IDEA创建maven项目时控制台输出中文乱码?在网上找了很多方法,搞了好一会才解决(我自己粗心造成的),现在来总结一下:1.IDEA-Help-Edit Custom VM Options-粘贴一句话:-Dfile.encoding=utf-8然后重启。2.File-Settings-Editor-FileEncodings中的三个选项都设置为UTF-8:3.找到IDEA安装路径下的bin目录中的idea.exe.vmoptions和idea64.exe.vmoptions文件,打开并在末

字符串表情替换_麻豆_matou的博客-程序员宝宝

博主最近在研究IM的实现,不想直接使用第三方的界面,于是就开始了自己的作死之路。今天把包含表情格式的文本转换成相应的富文本贴一下吧。首先,博主的表情格式是现在常用的中括号+标志符,类似[11]就是一个表情格式的字符。 我们需要实现的功能就是把形如: 你好[11] 这样的字符串变成: 你好 这样的字符串,具体的步骤就不再叙述了,注释已经很详细了/// 将字符串转换为含有表情的富文本...

推荐文章

热门文章

相关标签