当前位置: 首页 > news >正文

3.Default Constructor的构造操作

目录

1. 问题引入

2. 4种implicitly声明的default constructor


1. 问题引入

“default constructors......在需要的时候被编译产生出来”。关键词是“在需要的时候”,被谁需要,做什么事情?看看下面的代码,然后梳理下思路。

class Foo
{
public:int val;Foo *pnext;
};
void foo_bar()
{//程序要求bar's members都被清空为0Foo bar;if(bar.val || bar.pnext)// ... do something//...
}

在上面的代码中,正确的程序语意是要求Foo有一个default constructor,可以将它的两个members初始化为0。然而“在需要的时候”?答案是No,其中的差别是一个被程序需要,一个被编译器需要。程序如果需要,那是程序员的责任,本例中承担的责任是设计class Foo的人。是的,上述的代码不会合成一个default constructor。

那么什么时候合成一个default constructor?C++ Stand[ISO-C++95]的Section2.1这么说:对于class X,如果没有任何的user-declared constructor,那么会有一个default constructor 被implicitly(隐式)声明出来......一个被implicitly声明出来的default constructor 将是一个trivial(没啥用的)constructor。

下面分4种情况讨论default constructor 被implicitly声明出来。

2. 4种implicitly声明的default constructor

2.1)带有default constructor的member class object

如果一个class没有任何的constructor,但是它内含一个member object,而后者有一个default constructor,那么这个class 的implicit default constructor就是nontrivial,编译器需要为该class合成一个default constructor。举个例子,我们看看如下的代码,在这个代码中Bar会合成一个default constructor。

class Foo{
public:Foo();Foo(int);
};
class Bar{
public:Foo foo;char *str;
};
void foo_bar(){Bar bar;//Bar::foo必须在此处初始化。//Bar::foo是一个member object,而其//class Foo拥有default constructor,符合要求if(bar.str){}....
}

扩张后的代码可能是这样子。

//扩张后的default constructor
//C++伪码
Bar::Bar()
{foo.Foo::Foo();//附加上的compiler codestr = 0;//explicit user code
}

2.2)带有default constructor的Base Class

如果一个Base Class具有default constructor,而这个基类的derived class没有default constructor,此时derived class的default constructor会被视作nontrivial,因此需要被合成出来。他将调用上一层base class的default constructor(根据他们声明的顺序)。

2.3)“带有一个virtual function”的Class

另有两种情况,也需要合成default constructor:

  • Class 声明(或继承)一个virtual function。
  • Class派生一个继承串链,其中有一个或者更多的virtual base classes。

以下的程序为例子,每个class object中,一个额外的pointer member(也就是vptr)会被编译器合成出来,内含class 的virtual function地址。Widegt要合成一个default constructor,Bell也要合成一个default constructor,Whistle也要合成一个default constructor。

class Widget{
public:virtual void flip() = 0;
};
void flip(const Widget &widget)
{widget.flip();
}
class Bell:public Widget{
public:void flip(){cout<<"Bell"<<endl;}
};
class Whistle:public Widget{
public:void flip(){cout<<"Whistle"<<endl;}
};
void foo()
{Bell b;Whistle w;flip(b);flip(w);
}

2.4)“带有一个virtual base class”的Class

virtual base class的实现法在不同的编译器之间存在非常大的差异,然而每一种实现法的共同点在于必须使得virtual base class在其每一个derived class object中的位置,能够在执行期准备妥当。例如如下的代码,代码中A,B,C均需要合成一个default constructor,并在里面安插那些“允许每一个virtual base 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;};

http://www.lryc.cn/news/426716.html

相关文章:

  • CSS的:current伪类:精准定位当前活动元素
  • 搭建个人网站
  • 机器学习课程学习周报八
  • 福泰轴承股份有限公司进销存系统pf
  • 【k8s从节点报错】error: You must be logged in to the server (Unauthorized)
  • 风清扬/基于Java语言的光伏监控系统+光伏发电预测+光伏项目+光伏运维+光伏储能项目
  • Datawhale X 魔搭 AI夏令营第四期 魔搭-AIGC方向全过程笔记
  • 数组---怎么样定义和引用数组
  • Nginx—Rewrite
  • 《深入浅出WPF》读书笔记.5控件与布局(上)
  • 二叉树的判断
  • Hive3:常用的内置函数
  • 设计模式---构建者模式(Builder Pattern)
  • Pytorch中transform的应用
  • okular阅读软件简介
  • 【书生大模型实战营(暑假场)闯关材料】基础岛:第1关 书生大模型全链路开源体系
  • 掌握抽象工厂模式:打造灵活且强大的跨平台产品族
  • 【Hadoop】建立圈内组件的宏观认识(大纲版)
  • NFS主从同步Rsync、sersync2
  • uniapp项目中,在原有数据中增加选中的状态,数据不改变
  • WPF自定义控件
  • Java中的全局异常处理器 -- GlobalExceptionHandler
  • R语言文本挖掘-万字详细解析tm包
  • JWT中的Token
  • 苹果在iOS 18.1中向第三方开发者开放iPhone的NFC芯片
  • 系统开发之禁止卸载应用名单
  • wait 和 notify
  • docker 启动 mongo,redis,nacos.
  • Docker Swarm 搭建
  • 浅述TSINGSEE青犀EasyCVR视频汇聚平台与海康安防平台的区别对比