首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为虚拟基类的虚拟基类调用了错误的构造函数

是一个在面向对象编程中可能遇到的错误。它指的是在多重继承中,派生类通过虚拟继承(virtual inheritance)从多个虚拟基类派生,但在构造函数中错误地调用了虚拟基类的构造函数。

虚拟继承是为了解决多重继承带来的菱形继承(diamond inheritance)问题而引入的概念。在菱形继承中,派生类继承了两个或多个共同的基类,而这些共同的基类又继承自同一个虚基类。如果不使用虚拟继承,在派生类中就会存在多个共同基类的实例,而虚拟继承可以确保只有一个共同基类的实例。

当为虚拟基类的虚拟基类调用了错误的构造函数时,可能会导致派生类无法正确初始化虚拟基类的成员,进而引发各种错误和不可预测的行为。

针对这个问题,可以通过以下方式解决:

  1. 确认构造函数调用正确:检查派生类中的构造函数,确保在构造函数的成员初始化列表中正确调用了虚拟基类的构造函数。
  2. 检查派生类中的初始化顺序:虚拟基类的构造函数应该在派生类的构造函数的成员初始化列表中尽早被调用,以保证虚拟基类的成员在派生类的构造函数中正确初始化。
  3. 使用初始化顺序控制:如果派生类同时继承多个虚拟基类,可以使用初始化顺序控制来明确指定每个虚拟基类的构造函数调用顺序,以避免调用错误的构造函数。

在腾讯云的产品中,腾讯云提供了各种云计算相关的服务和解决方案,可以帮助开发者快速构建和部署应用。例如,云服务器(ECS)提供了可弹性伸缩的计算能力;对象存储(COS)提供了安全可靠的云端存储服务;人工智能服务(AI)提供了图像识别、语音识别等人工智能能力;数据库服务(CDB)提供了高性能、可扩展的数据库解决方案等等。你可以参考腾讯云的官方网站(https://cloud.tencent.com/)获取更详细的产品信息和文档。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++核心准则​讨论:将析构函数设为公共和虚拟,或受保护和非虚拟

析构函数应该是虚函数吗?也就是说,是否应该允许通过指向指针进行销毁?如果是,则base析构函数必须是公共才能被调用,否则虚拟调用它会导致未定义行为。...这种情况导致较早编码标准对所有析构函数都必须是虚拟提出了全面的要求。这太过分了(即使是常见情况);相反,规则应该是当且仅当析构函数是公共时,才将它们虚函数化。...析构可以看作只是另一种操作,尽管具有使非虚调用变得危险或错误特殊语义。因此,对于析构函数,选择是根据是否允许通过指向Base指针实际上调用它。“非虚”不是一种选择。...因此,如果可以调用(即是公共析构函数,则它是虚拟,否则是非虚拟。...注意,NVI模式不能应用于析构函数,因为构造函数和析构函数无法进行深度虚拟调用。(请参阅第39和55条。)

1.1K20

派生中虚函数和非虚函数继承效果

,因为eye是个普通函数,在编译阶段就确定好是被谁调用,所以他只认哪个指针指向自己,这里是Animal指针指向,所以他就调用Animal里面的,普通函数是父子类提供“强制实现”,也就是只要是父指针调用普通函数...,那就是父普通函数 而虚函数作用,主要是为了让父指针可以调用子类函数,这种是在运行时才决定调用哪个函数 1、虚函数:   C++函数主要作用是“运行时多态”,父中提供虚函数实现,子类提供默认函数实现...子类可以重写父函数实现子类特殊化。 2、纯虚函数:   C++中包含纯虚函数,被称为是“抽象”。抽象不能使用new出对象,只有实现了这个纯虚函数子类才能new出对象。   ...3、普通函数:   普通函数是静态编译,没有运行时多态,只会根据指针或引用“字面值”对象,调用自己普通函数。   普通函数是父子类提供“强制实现”。   ...因此,在继承关系中,子类不应该重写父普通函数,因为函数调用至于对象字面值有关。 参考链接

8410
  • 从零开始学C++之继承(二):继承与构造函数、派生转换

    一、不能自动继承成员函数 构造函数(包括拷贝构造函数) 析构函数 =运算符 二、继承与构造函数 构造函数不被继承,派生中需要声明自己构造函数。...声明构造函数时,只需要对本类中新增成员进行初始化,对继承来成员初始化调用构造函数完成(如果没有给出则默认调用默认构造函数)。...派生构造函数需要给构造函数传递参数 #include  using namespace std; class ObjectB { public:     ObjectB...从输出可以看出: 派生对象构造次序: 先调用对象成员构造函数,接着是构造函数,然后是派生对象成员构造函数,最后是派生自身构造函数。...初始化列表参数多个且其中有调用构造函数时,先执行构造函数(从最远开始,如果多重继承则按继承顺序);其他对象成员若不止一个,则按定义顺序构造,与初始化列表顺序无关。

    1.5K00

    C++编程经验(2):做虚析构函数必要性

    这个要提一下,如果记不住就记住:如果不做虚析构函数,会有内存泄漏 解释 定义一个指针p,在delete p时,如果析构函数是虚函数,这时只会看p所赋值对象,如果p赋值对象是派生对象,...就会调用派生析构函数;如果p赋值对象是对象,就会调用析构函数,这样就不会造成内存泄露。...如果析构函数不是虚函数,在delete p时,调用析构函数时,只会看指针数据类型,而不会去看赋值对象,这样就会造成内存泄露。 多少学点设计模式就清楚了。...接下来是一个子类 class Inherit :public Base{ //此处省去,一切从简 }; //重点看调用 int main() { Base *p = new Inherit; //这种方式调用

    58510

    C++核心准则C.35:析构函数要么是公开函数,要么是保护非虚函数

    C.35: A base class destructor should be either public and virtual, or protected and nonvirtual 析构函数要么是公开函数...为了避免无定义行为。如果析构函数是公有的,那么调用侧代码就会尝试使用指针销毁派生对象,在析构函数非虚函数时其结果时没有定义。...如果析构函数时保护,那么调用侧代码就无法通过类型指针销毁派生对象,这是析构函数就没有必要一定是虚函数。析构函数是保护而不是私有的,这样派生析构函数才能调用它。...通常,设计者不会知道在析构函数中应该执行什么样动作。...我们可以想象一种需要保护函数析构函数情况:当希望允许派生对象(只有这个类型)通过指针销毁另外一个对象(不是它自己)时。但是我们还没有在实际开发中遇到这种情况。

    1.1K20

    C++进阶-继承

    C++进阶-继承 零、前言 一、继承概念和定义 二、和派生对象赋值转换 三、继承中作用域 四、派生默认成员函数 五、继承和友元 六、继承和静态成员 七、菱形继承和虚拟继承 八、继承和组合...;如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用 注:默认构造函数:无参构造函数,编译器自动生成构造函数,全缺省构造函数 示图:无默认构造函数,且不显示调用 派生拷贝构造函数必须调用拷贝构造完成拷贝初始化...注:如果不调用,系统会自动调用父默认构造函数 示图: 注:调用拷贝构造用了切片操作 派生operator=必须要调用operator=完成复制 注:这里调用赋值同样也是切片操作...:一般不自行去主动调用析构函数,不然可能会造成错误 派生对象初始化先调用构造再调派生构造 派生对象析构清理先调用派生析构再析构 示图: 五、继承和友元 概念:...将该类构造函数访问权限设置私有,当派生调用构造函数时,会先调用父构造函数,而父构造函数不能被调用,无法构造对象也就构造不了派生对象(但这样不仅派生无法构造,该类自己也不能构造

    45850

    【C++】构造函数初始化列表 ② ( 构造函数 初始化列表 传递参数 | 嵌套情况下 构造函数 析构函数 执行顺序 )

    一、构造函数 初始化列表 传递参数 1、构造函数参数传递 构造函数 初始化列表 还可以使用 构造函数参数 ; 借助 构造函数参数列表 , 可以为 初始化列表 传递参数 ; 在下面的代码中...int heightOfA) : m_age(age), m_a(ageOfA, heightOfA) {} m_age(age) 表示 m_age 成员变量 赋值 构造函数参数中 age 参数..., A 定义了 2 个参数 有参构造函数 ; B 定义了 无参构造函数 , 但是在该 无参构造函数 中 , 定义了函数列表 B() : m_age(10), m_a(10, 150) , 在该函数列表中..., 执行了 A 构造函数 ; B 中还定义了 有参构造函数 , 接收 3 个参数 , 分别作为 m_age 成员值 , 和 A 类型成员对象 有参构造函数 2 个参数 , 这是 使用了...: 析构函数构造函数 执行顺序 相反 ; 2、代码示例 - 构造函数执行顺序 下面的代码中 , 在 B 中定义 A 类型 成员变量 ; 执行构造函数时 , 先调用 A 构造函数 , 再调用

    24730

    【学习C++篇】 继承(补充篇)

    派⽣构造函数必须⽤(默认构造自动调用)构造函数初始化那⼀部分成员。...如果没有默认构造函数,则必须在派⽣构造函数初始化列表阶段显⽰⽤(就是要写意思)(匿名对象初始化,下面例子有讲)。 2....派⽣拷⻉构造函数必须拷⻉构造完成拷⻉初始化。 3. 派⽣operator=必须要operator=完成复制。...派⽣析构函数会在被⽤完成后⾃动析构函数清理成员。因为这样才能保证派⽣对象先清理派⽣成员再清理成员顺序。 5. 派⽣对象初始化先调⽤构造再调派⽣构造。...例题加深理解 选A,解析如下 2.实现⼀个不能被继承 ⽅法1:构造函数私有,派⽣构成必须构造函数,但是构成函数私有化以后,派⽣看不⻅就不能⽤了,那么派⽣就⽆法实例化出对象

    5910

    移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——10.继承

    派生构造函数必须调用构造函数初始化那一部分成员。如果没有默认 构造函数,则必须在派生构造函数初始化列表阶段显示调用。 2....派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。 3. 派生operator=必须要调用operator=完成复制。 4....派生析构函数会在被调用完成后自动调用析构函数清理成员。因为这样才能 保证派生对象先清理派生成员再清理成员顺序。 5. 派生对象初始化先调用构造再调派生构造。...派生对象析构清理先调用派生析构再析构。//先子后父!!!!!! 7. 因为后续一些场景析构函数需要构成重写,重写条件之一是函数名相同(这个我们后面会讲 解)。...(s) //这里使用了拷贝构造,并使用了隐式类型转换,(因为父拷贝构造函数只有一 个参数,s会先被隐式类型转换为person类型,产生临时变量,临时变量再来通过父拷贝构造完成构造

    7110

    【C++修炼之路】15.C++继承

    4.1 派生构造函数 4.2 派生拷贝构造函数 4.3 派生赋值运算符重载 4.4 派生析构函数 4.5 总结 五.继承与友元 六.继承与静态成员 6.1 静态成员 6.2 确定是否解引用...发现顺序: 构造构造,派生构造。 析构: 派生先析构,后析构。 4.5 总结 派生构造函数必须调用构造函数初始化那一部分成员。...如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用。 派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。...因为这样才能保证派生对象先清理派生成员再清理成员顺序。 派生对象初始化先调用构造再调派生构造。 派生对象析构清理先调用派生析构再析构。...,因此下面打开内存窗口观察: 整体都作为D数据,D继承了A、B、C,由于菱形继承代码冗余,发现B和C继承下来A都存在在D中,而虚拟继承为了解决两个A同时出现,采用了以下策略:(下面改成虚拟继承代码

    54400

    【C++】继承

    答案是错误,因为构成重载函数前提是必须在同一作用域,和派生是两个不同域,所以并不构成重载,而是构成隐藏。...派生构造函数只能调用构造函数来初始化那部分成员,不能在自己构造函数里面初始化成员,值得注意是,如果有默认构造函数,那我们不需要管成员初始化工作,只要把派生自己成员在构造函数里面初始化即可...但如果没有合适默认构造,那则必须在派生初始化列表显示调用有参构造函数进行成员初始化。 2....拷贝构造函数构造不同,必须在派生拷贝构造初始化列表处显示调用拷贝构造,完成成员复制。在传参时有人可能会有疑问,调用拷贝构造该如何将子类中成员提取出来呢?...构造,两次析构,其实是因为我们显示调用了Person析构,编译器自己会自动调用析构,所以2次 // 子类先析构,父后析构。

    69910

    关于vtordisp知多少?

    字节偏移处,使用了4个字节存储了虚Basevtordisp。...MSDN给出解释是:虚继承中派生重写了函数,并且在构造函数或者析构函数中使用指向指针调用了函数,编译器会为虚添加vtordisp域。...然而,经过VS2010测试,我们发现上述示例代码便会产生vtordisp字段!条件是。 1. 派生重写了虚函数。 2. 派生定义了构造函数或者析构函数。...,它所解决问题是:由于对虚拟置换与对其派生置换之间有差异,可能会向虚函数传递错误 this 指针。 该解决方案向各个虚拟提供称作 vtordisp 字段单个构造置换调整。...曾经我遇到过一个虚拟继承实例,在对象初始化过程中会修改vtordisp字段,但是每次在初始化结束前都会把vtordisp减去一个常量使得它最终结果0。而且没有出现任何访问该字段汇编指令!

    80190

    C++之继承

    private成员在派生中是不能被访问,如果成员不想在外直接被访问,但需要在派生中能访问,就定义protected。可以看出保护成员限定符是因继承才出现。 3....下面是这几个成员函数应该注意几个点: 1. 派生构造函数必须调用构造函数初始化那一部分成员。如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用。 2....派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。 3. 派生operator=必须要调用operator=完成复制。 4....派生析构函数会在被调用完成后自动调用析构函数清理成员。因为这样才能保证派生对象先清理派生成员再清理成员顺序。 5. 派生对象初始化先调用构造再调派生构造。 6....派生对象析构清理先调用派生析构再析构。

    10310

    C++中继承

    private成员在派生中是不能被访问,如果成员不想在外直接被访问,但需要在 派生中能访问,就定义protected。可以看出保护成员限定符是因继承才出现。...派生默认成员函数 派生构造函数必须调用构造函数初始化那一部分成员。如果没有默认 构造函数,则必须在派生构造函数初始化列表阶段显示调用。...派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。 派生operator=必须要调用operator=完成复制。...派生析构函数会在被调用完成后自动调用析构函数清理成员。因为这样才能 保证派生对象先清理派生成员再清理成员顺序。 派生对象初始化先调用构造再调派生构造。...派生对象析构清理先调用派生析构再析构。 因为后续一些场景析构函数需要构成重写,重写条件之一是函数名相同(这个我们后面会讲 解)。

    6710

    C++之继承

    继承后父成员(成员变量+成员函数)都变成子类一部分,子类复用了成员。 2.定义 1.格式 2.继承关系和访问限定符 继承方式和访问限定符所使用关键字是一样,但他们功能不同。...当派生中定义与父类同名成员时,派生将屏蔽对该成员直接访问,称这种情况隐藏。而派生同名成员是对成员重写/重定义。...fun函数并不构成重载,因为他们在不同作用域,他们是隐藏关系 四、派生默认成员函数 1.构造函数 派生构造函数必须调用构造函数初始化那一部分成员,如果没有默认构造函数,派生就必须在初始化列表处显示调用构造函数...派生对象初始化时,会先调用构造函数,再调用派生构造函数。 2.拷贝构造 必须调用拷贝构造完成部分拷贝构造。...编译器会对析构函数函数名进行特殊处理,即派生析构函数名都会被处理destructor()。因此派生析构函数回构成隐藏。

    41410

    中承上启下角色——继承

    这里体现出了 Student和Teacher复用了Person成员。下面我们使用监视窗口查看Student和Teacher对象,可 以看到变量复用。调用Print可以看到成员函数复用。...派生构造函数必须调用构造函数初始化那一部分成员。如果没有默认 构造函数,则必须在派生构造函数初始化列表阶段显示调用。 2....派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。 3. 派生operator=必须要调用operator=完成复制。 4....派生析构函数会在被调用完成后自动调用析构函数清理成员。因为这样才能 保证派生对象先清理派生成员再清理成员顺序。 5. 派生对象初始化先调用构造再调派生构造。...派生对象析构清理先调用派生析构再析构。 7. 因为后续一些场景析构函数需要构成重写(多态中一种父子成员函数关系),重写条件之一是函数名相同(重写条件之一隐藏条件)。

    75330

    《挑战30天C++入门极限》图文例解C++多重继承与虚拟继承

    ,C++允许一个派生指定多个,这样继承结构被称做多重继承。...float tonnage) :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage) //多重继承要注意调用构造函数...AmphibianCar获得了来自两个SetWeight()成员函数,当我们调用a.SetWeight(3)时候计算机不知道如何选择分别属于两个被重复拥有了成员函数SetWeight()...由于这种模糊问题存在同样也导致了AmphibianCar a(4,200,1.35f);执行失败,系统会产生Vehicle”不是或成员错误。   ...以上面的代码例,我们要想让AmphibianCar既获得一个Vehicle拷贝,而且又同时共享用Car与Boat数据成员与成员函数就必须通过C++所提供虚拟继承技术来实现。

    42510

    【C++】万字一文全解【继承】及其特性__(20)

    之间关系可以用 继承,可以用组合,就用组合 [1]白箱复用——继承 继承允许你根据实现来定义派生实现。这种通过生成派生复用通常被称 白箱复用(white-box reuse)。...派生构造函数必须调用 构造函数初始化那一部分成员。如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用。...派生拷贝构造函数必须调用 拷贝构造完成拷贝初始化。 派生operator=必须要调用 operator=完成复制。...派生析构函数会在被调用完成后自动调用 析构函数清理成员。因为这样才能 保证派生对象先清理派生成员再清理成员顺序。 派生对象初始化先调用 构造再调派生构造。...派生对象析构清理先调用派生析构再 析构。 因为后续一些场景析构函数需要构成重写,重写条件之一是函数名相同(多态条件)。

    15610

    C++中继承

    _name; // 姓名 }; ⭐1.派生构造函数必须调用构造函数初始化那一部分成员。...如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用。...如下图中,构造函数不是默认,因此需要派生中写出构造函数,并且在初始化列表中去调用构造函数。 ⭐2.派生拷贝构造函数必须调用拷贝构造完成拷贝初始化。...如果非要去显示调用的话,可能会出现对同一空间析构了两次情况。因为在派生析构函数中析构了一次,然后到时候,析构函数又调用了一次,这样就会报错!...派生对象析构清理先调用派生析构再析构。 继承与友元 一句话:友元关系不能继承,也就是说友元不能访问子类私有和保护成员。

    98930

    【c++】C++中继承&&菱形继承详解

    这里体现出了 //Student和Teacher复用了Person成员。下面我们使用监视窗口查看Student和Teacher对象,可 //以看到变量复用。调用Print可以看到成员函数复用。...派生构造函数必须调用构造函数初始化那一部分成员。...如果没有默认构造函数,则必须在派生构造函数初始化列表阶段显示调用 派生拷贝构造函数必须调用拷贝构造完成拷贝初始化 派生operator=必须要调用operator=完成复制...派生析构函数会在被调用完成后自动调用析构函数清理成员。...因为这样才能 保证派生对象先清理派生成员再清理成员顺序 派生对象初始化先调用构造再调派生构造 派生对象析构清理先调用派生析构再析构 因为后续一些场景析构函数需要构成重写,重写条件之一是函数名相同

    14010
    领券