C++ 虚继承派生类构造函数的写法
来源:互联网 发布:什么软件可以升级win10 编辑:程序博客网 时间:2024/06/11 10:23
昨天做题时候发现的问题
普通的继承中,我们可以在当前类(C)构造函数的初始化表中指明如何去构造直接父类(B),然后在该父类(B)构造函数的初始化表中指明如何构造祖先类(A)。
示例代码
class A{public: A() {} A(int d):data(d) {}private: int data;};class B : public A{public: B() {} B(int x):A(x) {}};class C : public B{public: C() {} C(int x):B(x) {}};
这样的写法是正确的,在创建一个 C 类型的实例时,程序会根据其构造函数的选择以及参数化表层层找到最上层的类,然后依次往下执行构造函数进行初始化。
但是在继承链中如果存在虚继承的话或许就不是这样了。
程序中有四个类: animal、aqu_animal、amp_animal、test
其中类之间的继承关系如下,除 test
以外其他继承都采用虚继承的方式。
示例代码
这里还是按照原来的思路进行初始化的工作
#include <iostream>#include<stdio.h>using namespace std;class animal{protected: int height; int weight; char sex;public: animal() { cout<<"animal()"<<endl; } animal(int h,int w,char s): height(h),weight(w),sex(s) { cout<<"animal(int h,int w,char s)"<<endl; }};class aqu_animal:virtual public animal{protected: int swimming_speed;public: aqu_animal() { cout<<"aqu_animal()"<<endl; } aqu_animal(int h,int w,char s,int s_p): animal(h,w,s),swimming_speed(s_p) { cout<<"aqu_animal(int h,int w,char s,int s_p)"<<endl; }};class amp_animal:virtual public aqu_animal{public: amp_animal() { cout<<"amp_animal()"<<endl; } amp_animal(int h,int w,char s,int s_p,int r):aqu_animal(h,w,s,s_p),running_speed(r) { cout<<"amp_animal(int h,int w,char s,int s_p,int r)"<<endl; } void show() { cout<<"height:"<<height<<endl; cout<<"weight:"<<weight<<endl; cout<<"sex:"<<sex<<endl; cout<<"swimming_speed:"<<swimming_speed<<endl; cout<<"running_speed:"<<running_speed<<endl; }private: int running_speed;};class test:public amp_animal{public: test() {} test(int h,int w,char s,int s_p,int r):amp_animal(h,w,s,s_p,r) { cout<<"test(int h,int w,char s,int s_p,int r)"<<endl; cout<<"----------------"<<endl; amp_animal::show(); }};int main(){ test t(50,20,'m',100,120); return 0;}
执行结果
animal()aqu_animal()amp_animal(int h,int w,char s,int s_p,int r)test(int h,int w,char s,int s_p,int r)----------------height:4309616weight:7012244sex:swimming_speed:1978756045running_speed:120
可以看到,除了 running_speed
正常外其他的变量都没有被正常赋值。
在函数的调用中,我们发现 test
类中的 test(int h,int w,char s,int s_p,int r)
正常执行了,并且它所附带的初始化表中的构造函数同样也被执行了( amp_animal(int h,int w,char s,int s_p,int r)
)。
而在 amp_animal
类中利用 amp_animal(int h,int w,char s,int s_p,int r)
构造时的父类 aqu_animal
构造函数 aqu_animal(int h,int w,char s,int s_p)
并没有被执行,同样 animal
类中的 animal(int h,int w,char s)
也没有被执行,实际上都是调用了它们缺省的构造函数。
原因以及解决方法
在 C++
中,如果继承链上存在虚继承的基类,则最底层的子类要负责完成该虚基类部分成员的构造。
即我们需要显式调用虚基类的构造函数来完成初始化,如果不显式调用,则编译器会调用虚基类的缺省构造函数,若虚基类中没有定义的缺省构造函数,则会编译错误。
因为如果不这样做,虚基类部分会在存在的多个继承链上被多次初始化。
很多时候,对于继承链上的中间类,我们也会在其构造函数中显式调用虚基类的构造函数,因为一旦有人要创建这些中间类的对象,我们要保证它们能够得到正确的初始化。
改法
#include <iostream>#include<stdio.h>using namespace std;class animal{protected: int height; int weight; char sex;public: animal() { cout<<"animal()"<<endl; } animal(int h,int w,char s): height(h),weight(w),sex(s) { cout<<"animal(int h,int w,char s)"<<endl; }};class aqu_animal:virtual public animal{protected: int swimming_speed;public: aqu_animal() { cout<<"aqu_animal()"<<endl; } aqu_animal(int h,int w,char s,int s_p): animal(h,w,s),swimming_speed(s_p) { cout<<"aqu_animal(int h,int w,char s,int s_p)"<<endl; }};class amp_animal:virtual public aqu_animal{public: amp_animal() { cout<<"amp_animal()"<<endl; } amp_animal(int h,int w,char s,int s_p,int r):aqu_animal(h,w,s,s_p),running_speed(r),animal(h,w,s) { cout<<"amp_animal(int h,int w,char s,int s_p,int r)"<<endl; } void show() { cout<<"height:"<<height<<endl; cout<<"weight:"<<weight<<endl; cout<<"sex:"<<sex<<endl; cout<<"swimming_speed:"<<swimming_speed<<endl; cout<<"running_speed:"<<running_speed<<endl; }private: int running_speed;};class test:public amp_animal{public: test() {} test(int h,int w,char s,int s_p,int r):amp_animal(h,w,s,s_p,r),aqu_animal(h,w,s,s_p),animal(h,w,s) { cout<<"test(int h,int w,char s,int s_p,int r)"<<endl; cout<<"----------------"<<endl; amp_animal::show(); }};int main(){ test t(50,20,'m',100,120); return 0;}
注意 test
的构造函数初始化表中我们显式的调用了其间接父类的构造函数。
执行结果
animal(int h,int w,char s)aqu_animal(int h,int w,char s,int s_p)amp_animal(int h,int w,char s,int s_p,int r)test(int h,int w,char s,int s_p,int r)----------------height:50weight:20sex:mswimming_speed:100running_speed:120
- C++ 虚继承派生类构造函数的写法
- 一般----派生类构造函数的写法
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
- 多重继承派生类的构造函数
- 多重继承派生类的构造函数
- 多重继承派生类的构造函数
- 继承与派生:派生类的构造函数
- 继承与派生:虚基类及其派生类的构造函数
- 三十九、继承与派生:派生类的构造函数****
- 第十一周 领会继承以及基类、派生类中构造函数的写法以及执行过程
- C++(继承时的名字遮蔽&&派生类的构造函数)
- c++ 单继承派生类的构造函数
- 7.27多重继承派生类的构造函数
- 多重继承中派生类的构造函数
- 派生类构造函数和多重继承的二义性问题
- 类的继承与派生中关于构造函数
- React Native-组件的引用
- PAT-乙级 1001. 害死人不偿命的(3n+1)猜想 (15)
- WEB-INF目录与META-INF目录的作用
- ps 切图
- svn移动仓库数据并且账号不丢失的解决办法
- C++ 虚继承派生类构造函数的写法
- 【堆】堆排序
- 在JAVAWEB项目中用JSP生成数据库数据曲线图
- 文章标题
- Oracle数据库中计算时间差的常用表达式
- 12.Springboot 之 使用Scheduled做定时任务
- Mac下AndroidStudio中手动配置Gradle
- OpenCV: OpenCV人脸检测框可信度排序
- Feign和Hystrix异常熔断的理解