首页 > 编程语言 >C++虚基类

C++虚基类

时间:2023-01-04 18:00:11浏览次数:35  
标签:int C++ B1 B2 基类 public 构造函数


文章目录

  • ​​1、为什么要引入虚基类​​
  • ​​2、虚基类的概念​​
  • ​​3、虚基类的初始化​​
  • ​​4、关于虚基类子类构造函数​​
  • ​​5、虚基类构造函数调用顺序​​

1、为什么要引入虚基类

如果一个派生类是从多个基类派生出来的,而这些基类又有一个共同的基类,则在这个派生类中访问这个共同的基类中的成员时,可能会产生二义性。

比如有以下结构

class  B{
protected: int a;
public: B( ){ ...} };
class B1: public B{
public: base1( ){...} };
class B2: public B{
public: B2( ){...} };
class D:public B1,public B2{ . . .}

C++虚基类_构造函数


C++虚基类_初始化_02


以下程序会报错,因为a具有二义性。

class B {
protected:
int a;
public:
B( ){ a=5; cout<<"B a="<<a<<endl;} };
class B1:public B{
public:
B1( ){ a=a+10; cout<<"B1 a="<<a<<endl;} };
class B2:public B{
public:
B2( ){ a=a+20; cout<<"B2 a="<<a<<endl;} };
class D:public B1,public B2{
public:
D( ){ cout<<"D a="<< a<<endl;} };
//将D的构造函数改成如下结构能够通过运行
// D( ){ cout<<"B1 a="<<B1:: a<<endl; cout<<"B2 a="<< B2::a<<endl;} };
int main( )
{ D obj; return 0; }
B a=5
B1 a=15
B a=5
B2 a=25
B1 a=15
B2 a=25

能够看到a被初始化了两次,我们希望a只被再第一次初始化以后就不再继续初始化了。那么我们要使用虚基类。

2、虚基类的概念

如果将公共基类说明为虚基类。那么,对同一个虚基类的构造函数只调用一次,这样从不同的路径继承的虚基类的成员在内存中就只拥有一个拷贝。从而解决了以上的二义性问题。

继承方式

class  派生类名:继承方式 virtual 基类名
{ … }

class 派生类名: virtual 继承方式 基类名
{ … }

我们将上面的继承结构改成如下所示

class B{
protected: int a;
public: B( ){ ...} };
class B1: public virtual B{
public: B1( ){...} };
class B2: public virtual B{
public: B2( ){...} };
class D:public B1,public B2{ . . .}

C++虚基类_虚基类_03


C++虚基类_构造函数_04

3、虚基类的初始化

虚基类的初始化与一般的多重继承的初始化在语法上基本上是一样的,但有一些特殊的规定:
对同一个虚基类的构造函数只调用一次,且是在第一次出现时调用;

修改后代码

class B {
protected:
int a;
public:
B( ){ a=5; cout<<"B a="<<a<<endl;} };
class B1:public virtual B{
public:
B1( ){ a=a+10; cout<<"B1 a="<<a<<endl;} };
class B2:public virtual B{
public:
B2( ){ a=a+20; cout<<"B2 a="<<a<<endl;} };
class D:public B1,public B2{
public:
D( ){ cout<<"D a="<< a<<endl;} };
int main( )
{ D obj; return 0; }

运行结果

B    a=5
B1 a=15
B2 a=35
D a=35

可以看到a只被初始化了一次。

4、关于虚基类子类构造函数

如果在虚基类中定义有带形参的构造函数,并且没有定义默认形式的构造函数,则整个继承结构中,所有直接或间接的派生类都必须在构造函数的成员初始化表中列出对虚基类构造函数的调用,以初始化在虚基类中定义的数据成员。

class B {  int a;
public:
B(int sa)
{ a=sa; cout<<"Constructing B"<<endl; } };
class B1:virtual public B{ int b;
public:
B1(int sa,int sb):B(sa)
{ b=sb; cout<<"Constructing B1"<<endl; } };
class B2:virtual public B{ int c;
public:
B2(int sa,int sc):B(sa)
{ c=sc; cout<<"Constructing B2"<<endl; } };
class D:public B1,public B2 {
int d;
public:
D(int sa,int sb,int sc,int sd): B(sa),B1(sa,sb),B2(sa,sc)
{ d=sd; cout<<"Constructing D"<<endl;} };
int main()
{ D obj(2,4,6,8); return 0; }

任何一个类的上层(不一定是直接继承虚基类),只要含有虚基类都要再构造函数中调用虚基类的构造函数。

运行结果

Constructing B
Constructing B1
Constructing B2
Constructing D

5、虚基类构造函数调用顺序

若同一层次中同时包含虚基类和非虚基类,应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类构造函数;

class X∶public Y,virtual public Z{
//…
};
X one;
定义类X的对象one后,将产生如下的调用次序。
Z( );
Y( );
X( );


标签:int,C++,B1,B2,基类,public,构造函数
From: https://blog.51cto.com/u_14597003/5988781

相关文章

  • Java和C++通过Socket通信中文乱码的解决
    理想的开发状态是我开始就是C开发,一直是C的开发,现在还是C的开发,若干年后,幸运的话,我可以成为C语言的高手或者专家……更实际的情况是我开始是C开发,后来变成了JAVA开发,然后......
  • C++_类和结构体
    面向对象编程类-abstractionC++类和结构体三种类类型是结构、类和联合。它们使用struct、class和union关键字进行声明。类和结构是用于定义你自己的类型的构造......
  • C++ invoks Python ~ int64_t and __int64
     #include<Python.h>intmain(){return}利用如上代码(cpppython.cc)测试C++调用python(version2.6.2),g++编译出现如下错误:通过错误可知__int64不是C++的支持的整型类......
  • C/C++球场预约信息管理系统
    C/C++球场预约信息管理系统四、设计基本要求1.只能使用C语言编程,除能使用平台所带的系统标准函数外,不能使用第三方的软件包2.要有使用多级文本菜单界面,3.要有良......
  • 《安富莱嵌入式周报》第294期:将C/C++代码转换为各种高级语言,超炫渲染着色器,VS2022新闻
    ​​​​更新视频教程:USB应用实战视频教程第5期:手把手玩转USBHID免驱方式下位机和QT6.4上位机开发上篇视频版:​​https://www.bilibili.com/video/BV1MK41197wC​​1、将C/......
  • 【C++】以最快的速度求一个数的因数之和
    源代码: #include<iostream>usingnamespacestd;intmain(){inta,b=0;cin>>a;for(inti=2;i<a;i++){if(a%i==0){b+=i;......
  • C++_控制结构和pipeline
    控制结构过程式编程范式叫做——指令式编程,而把函数式编程范式叫做——声明式编程过程式编程范式控制结构允许程序根据不同的状态、条件和参数来选择不同的处理和执行......
  • 工厂模式C++实现 (内附简单源码实现)
    抽象工厂模式为什么要用抽象工厂模式?*举个实际应用的例子,一个显示器电路板厂商,旗下的显示器电路板种类有非液晶的和液晶的;这个时候,厂商建造两个工厂,工厂A负责生产非......
  • C++ | 4-易用性改进
    使用auto自动类型推断,顾名思义,就是编译器能够根据表达式的类型,自动决定变量的类型(从C++14开始,还有函数的返回类型),不再需要程序员手工声明。但需要说明的是,auto并没有......
  • C++ 数学与算法系列之牛顿、二分迭代法求解非线性方程
    1.前言前文介绍了如何使用“高斯消元法”求解线性方程组。本文秉承有始有终的态度,继续介绍“非线性方程”的求解算法。本文将介绍2个非线性方程算法:牛顿迭代法。二......