`
codepeak
  • 浏览: 32582 次
  • 性别: Icon_minigender_1
  • 来自: 南京
最近访客 更多访客>>
社区版块
存档分类
最新评论

虚继承的构造函数调用问题

阅读更多
在某一个虚基类的任何一个派生类的构造函数中,都要将该虚基类的构造函数显示列出来。
包含虚基类的派生类对象的构造函数的调用顺序如下:
  1. 虚基类的构造函数在非虚基类之前调用。
  2. 若同一层次中包含多个虚基类,这些虚基类的构造函数按它们说明的顺序调用。
  3. 若虚基类由非虚基类派生而来,则仍然按照先调用基类的构造函数,再调用派生类的构造函数的执行顺序。
#include <iostream>

using namespace std;

class base{
	int x;
public:
	base(int i){
		cout<<(x = i)<<endl;
	}
};

class A1 : virtual base{
public:
	A1(int i):base(i){}
};

class A2 : virtual base{
public:
	A2(int i):base(i){}
};

class C: public A1,public A2{
public:
	C(int i):A1(i+1),A2(i+2){}
};

int main(){
	C c(1);
}

程序报错:找不到base类的默认构造函数
说明:
        在类C实例化要调用base的构造函数,因为没有显示给出,所以编译器试图调用base的默认构造函数,但是程序没有提供,所以报错。
        当采用虚继承时,最终派生类对象中只有一个虚基类的对象,因此该虚基类的对象只要构造一次即可(由此支持多继承)。而且该构造函数是在最终的派生类构造函数中调用的,中间派生类不调用虚基类的构造函数。
        在本例中,要定义C类的对象c,C类的构造函数直接调用base类的构造函数,来构造唯一的对象,虽然该对象也属于c中A1,A2的无名对象,但是A1,A2的构造函数列表中对base构造函数的调用被忽略。
        改正方法:
        将类C的构造函数改成C(int i):base(i),A1(i+1),A2(i+2){}或者给base类添加默认构造函数都可。
        可以看出在A1,A2中对类base的构造函数都没有调用,当然如果直接定义A1或A2的对象,则类base的构造函数要被调用。
分享到:
评论

相关推荐

    C++ 虚继承对基类构造函数调用顺序的影响

    继承作为面向对象编程的一种基本特征,其使用频率...  假设derived 虚继承自base类,那么derivd与base是一种“has a”的关系,即derived类有一个指向base类的vptr。(貌似有些牵强!某些编译器确实如此)  因此虚

    构造函数不能为虚函数的理由

    从实现上看,vtable 在构造函数调用后才建立,因而构造函数不可能成为虚函数。从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象...

    基类子类虚函数的调用顺序问题

    当我们讨论基类与子类的虚函数调用顺序时,这涉及到构造函数的执行流程以及对象初始化的过程。 首先,我们需要理解C++对象的构造过程。当创建一个对象时,构造函数会按照继承层次自底向上依次调用,即先调用最底层...

    为什么构造函数不能是虚函数

    - 这是因为构造函数调用的顺序是从基类到派生类,而在构造函数中调用虚函数时,虚拟表(VTable)中的指针还未被更新为最终派生类的版本,导致调用的总是当前类的函数。 4. **潜在的安全问题** - 如果允许在构造函数...

    构造函数不能声明为虚函数,析构函数可以声明为虚函数

    构造函数不能声明为虚函数主要是因为构造过程中对象的动态类型尚未确定,而析构函数可以声明为虚函数以确保正确释放资源并避免内存泄漏等问题。理解这些基本原则对于编写高质量、健壮的C++程序至关重要。

    c++ 构造函数中调用虚函数的实现方法

    然而,当我们尝试在构造函数中调用虚函数时,情况变得稍微复杂一些。下面我们将详细讨论这个问题。 首先,理解C++对象的构造过程至关重要。在创建一个对象时,构造函数会按照继承层次自底向上顺序执行。这意味着先...

    C++箴言:避免析构函数调用虚函数

    ### C++箴言:避免析构函数调用虚函数 #### 概述 在C++编程中,理解和遵循良好的设计模式对于确保程序的稳定性和可维护性至关重要。其中一个经常被提及的原则是“避免在析构函数中调用虚函数”。这一原则在C++语言...

    派生类构造函数和析构函数的执行顺序

    这是因为,构造函数是在对象创建时被调用的,而虚函数是在对象已经创建后被调用的。 派生类构造函数和析构函数的执行顺序是非常重要的。正确地理解和使用这两个函数,可以实现代码的重复利用和提高程序的效率。

    C++构造函数,复制构造函数和析构函数专题[1].pdf

    虚继承会导致二义性,因此在内存布局中引入了额外的指针来解决这个问题。每个虚继承的子类对象都会有一个指向基类的指针,以确保正确访问基类的数据。 总之,理解并熟练运用构造函数、复制构造函数、析构函数、继承...

    构造函数Demo

    1. 构造函数不能被继承,但可以通过基类的构造函数来调用(使用`base`关键字)。 2. 构造函数可以链式调用,即子类构造函数中可以调用基类的构造函数。 3. 构造函数不能是虚方法或抽象方法,也不能声明为static。 ...

    C++有子对象的派生类的构造函数

    2. 显式构造函数调用:可以使用成员初始化列表(member initialization list)来指定子对象的构造函数,并传递参数。这种方式可以提高效率,因为避免了默认构造后再赋值的额外开销。 三、派生类构造函数 1. 继承...

    C++类继承之子类调用父类的构造函数的实例详解

    C++类继承之子类调用父类的构造函数的实例详解 C++类继承是一种重要的面向对象编程技术,通过继承可以实现代码的重用和模块化。在C++类继承中,子类可以继承父类的成员变量和成员函数,但是在子类中调用父类的构造...

    为何要虚析构函数.docx

    此外,虚函数对应的虚函数表是存放在对象的内存空间里,如果构造函数是虚函数,就需要通过虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到虚函数表,所以构造函数不能是虚函数。 虚析构函数...

    C++派生类的构造函数

    5. 继承的构造函数:C++11引入了继承构造函数的概念,允许派生类直接使用基类的构造函数,这使得代码更简洁且易于理解。例如: ```cpp class Derived : public Base { public: using Base::Base; // 继承所有Base...

    一起学C#:构造函数和析构函数.rar

    2. **非虚函数**:析构函数是非虚的,这意味着不能通过继承链来调用它,只能由垃圾回收器在对象即将被销毁时调用。 3. **无需调用**:与构造函数不同,程序员不需要显式调用析构函数,它会在对象生命周期结束时自动...

    C++中的类中函数调用

    4. **构造函数与析构函数调用**:构造函数用于初始化对象,而析构函数则用于释放对象占用的资源。它们通常在对象的创建和销毁时自动调用。 ### 示例分析 在给定的代码示例中,我们看到一个名为`XS`的基类,以及三...

    c#析构构造函数c#析构构造函数c#析构构造函数

    C#中的析构构造函数(Destructor)是一种特殊的方法,它在对象即将被垃圾回收器清除时执行,用于释放非托管资源。在C#中,析构函数以`~`符号开头,后面跟着类名,例如`~MyClass()`. 它们不同于常规的构造函数,构造...

    验证有继承时的调用顺序

    不过,如果未使用虚继承,那么每个子类都会有自己的基类实例,相应的构造函数和析构函数也会被调用多次。 4. **虚基类**: 虚继承是为了处理多继承中的二义性问题,确保所有子类都只有一个特定基类的实例。当一个...

    C# 构造函数如何调用虚方法

    C# 构造函数如何调用虚方法是一个重要的知识点,了解这个问题可以帮助开发者更好的理解和使用 C# 语言中的虚方法和构造函数。 首先,需要了解什么是虚方法。在 C# 中,用 virtual 关键字修饰的方法(属性、事件)...

Global site tag (gtag.js) - Google Analytics