#include <iostream>
using namespace std;
class A{
int data_a;
public:
A(){
data_a = ;
cout << "A" << endl;
}
A(int a){
data_a = a;
cout << "A(a)" << endl;
}
void show(){
cout << data_a << endl;
}
~A(){
cout << "~A" << endl;
}
};
class B :public A{
int data_b;
public:
B(){
data_b = ;
cout << "B" << endl;
}
B(int a, int b) :A(a){
data_b = b;
cout << "B(a)" << endl;
}
void show(){
A::show();
cout << data_b << endl;
}
~B(){
cout << "~B" << endl;
}
};
class C :public A{
int data_c;
public:
C(){ data_c = ; cout << "C" << endl; }
C(int a, int b) :A(a){
data_c = b;
cout << "C(a)" << endl;
}
void show(){
A::show();
cout << data_c << endl;
}
~C(){
cout << "~C" << endl;
}
};
class D :public B, public C{
int data_d;
public:
D(){ data_d = ; cout << "D" << endl; }
D(int a, int b, int c, int d) :B(a, b), C(a, c){
data_d = d;
cout << "D(a)" << endl;
}
void show(){
B::show();
C::show();
cout << data_d << endl;
}
~D(){
cout << "~D" << endl;
}
};
int main()
{
A a(1) ;
B b(1,2);
C c(1,3);
D d(,,,);
a.show();
b.show();
c.show();
d.show();
a.~A();
b.~B();
c.~C();
d.~D();
system("pause");
return ;
}

程序运行结果没什么好说的。

下面开始变了:首先

class B :virtual public A{}
class C :virtual public A{}

将B C都是虚继承A,程序输出如下:

这里可以看到当B和C都是虚继承A的时候,在BC初始化的时候调用了A(a),在定义并初始化D的时候,只调用了一次A()(注意这里是A(),而不是A(a),因为子类中并没有显示的调用A的构造函数,所以默认调用A的无参构造函数),所以最终D输出的值是1 2 1 3 4.同时在释放的时候也只在最后调用一次A的析构函数。

现在将B和C依次变成虚继承

1、B虚继承A,C正常继承。输出如下:

2、C虚继承A,B正常继承。输出如下:

这里可以看到总是先调用了A(),然后才依次调用带参数的构造函数。所以这里可以看到show的值有不一样的,因为虚继承调用的是不带参数的构造函数。另外调用了两次A的构造函数因此也要调用两次析构函数。注意析构函数的调用顺序。

最后我们在D的构造函数中显示的调用A的构造函数 同样四种情况

D(int a, int b, int c, int d) :B(a, b), C(a, c),B::A(a){

这里A的构造函数分别限定使用B和C。以及B和C依次虚继承。输出如下:

可以看出,除了构造函数的调用遵循 先虚继承后非虚继承。但是都是调用了A的带参数的构造函数。

C++继承,多重继承,虚继承的构造函数以及析构函数的调用顺序问题的更多相关文章

  1. C++ 构造函数和析构函数的调用顺序、虚析构函数的作用

    构造函数和析构函数的调用顺序 构造函数的调用顺序: 当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止. 析构函数的调用书序: ...

  2. C++C++中构造函数与析构函数的调用顺序

    http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2 ...

  3. C++中构造函数和析构函数的调用顺序

    一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的 ...

  4. C++学习笔记(7)----类的数组中构造函数和析构函数的调用顺序

    C++类的数组中构造函数和析构函数的调用顺序(2) 对于如下的代码: #include<iostream> using namespace std; class CBase { priva ...

  5. C++构造函数和析构函数的调用顺序

    1.构造函数的调用顺序 基类构造函数.对象成员构造函数.派生类本身的构造函数 2.析构函数的调用顺序 派生类本身的析构函数.对象成员析构函数.基类析构函数(与构造顺序正好相反) 3.特例 局部对象,在 ...

  6. C++:派生类的构造函数和析构函数的调用顺序

    一.派生类 在C++编程中,我们在编写一个基类的派生类时,大致可以分为四步: • 吸收基类的成员:不论是数据成员还是函数成员,派生类吸收除基类的构造函数和析构函数之外的全部成员. • 改造基类函数:在 ...

  7. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

  8. C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容

    一.本文目的与说明 1. 本文目的:理清在各种继承时,构造函数.复制构造函数.赋值操作符.析构函数的执行顺序和执行内容. 2. 说明:虽然复制构造函数属于构造函数的一种,有共同的地方,但是也具有一定的 ...

  9. C++_day8_ 多重继承、钻石继承和虚继承

    1.继承的复习 1.1 类型转换 编译器认为访问范围缩小是安全的. 1.2 子类的构造与析构 子类中对基类构造函数初始化只能写在初始化表里,不能写在函数体中. 阻断继承. 1.3 子类的拷贝构造与拷贝 ...

随机推荐

  1. Android studio打开之后 cannot load project: java.lang.NUllpointerException

    参考来源:http://bbs.csdn.net/topics/391014393 关闭网络,重新打开Android studio就好了.(但是原因不清楚是为什么?) Internal error.  ...

  2. Homebrew安装及使用

    简介 Homebrew官网:http://brew.sh/index_zh-cn.html Homebrew是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件,相当于linux ...

  3. 让powershell同时只能运行一个脚本(进程互斥例子)

    powershell,mutex,互斥,进程互斥,脚本互斥 powershell脚本互斥例子,在powershell类别文章中,声明原创唯一. powershell 传教士 原创文章 2016-07- ...

  4. 不使用ASP.NET中的服务器控件将如何上传文件?

    遇到文件的上传时,可能会有大部分的开发者喜欢使用服务器控件,虽然很方便,但是却不能很好的控制,不具灵活性. 现给出例子,使用html标签语言灵活的控制文件的上传. 1.html部分 <input ...

  5. Mysql 连接sleep状态问题解决。

    昨日mysql总是出问题,各种程序在运行时,出现了连接已断开的问题.  导致此问题的原因: 1. 最大连接数 2. 网络问题 3. mysql服务器资源问题 然而,上面最常见的3个问题都没有出现.后来 ...

  6. as follows ,as follow && following

    在现在牛津英语上,as follow 和 as follows 用法差不多的,但后者更常用,不是说谁指一个谁指好几个.牵强附会! 为了保证正确性,你应该用as follows,单数的最好少用.意义差不 ...

  7. iOS thirdKeyboard Develop (APP Extension)

    如果需要开发第三方键盘 首先得了解一下苹果官方文档  https://developer.apple.com/library/ios/documentation/General/Conceptual/ ...

  8. Android开源框架:Universal-Image-Loader解析(四)TaskProcess

    Universal-Image-Loader中,对Task的处理有两种方法:FIFO,LIFO 在core/assist下的deque包中,其主要是定义了LIFOLinkedBlockingDeque ...

  9. linux下进程突然断掉后的日志查询

    最近写了一个实现监控的服务,可某天去看的时候进程突然木有了,这就捉急了,好好的是啥原因了呢?不会有人不小心把偶的进程关掉了把! 后发现一个linux日志文件:/var/log/messages 打开文 ...

  10. CGBitmapContextCreate函数参数详解

    函数原型: CGContextRef CGBitmapContextCreate ( void *data, size_t width, size_t height, size_t bitsPerCo ...