钻石(菱形)继承和虚基类

钻石(菱形)继承

如图,B,C继承了A,D继承了B,C

在这种情况下,如果D类的对象通过B、C两个不同的作用域调用A的数据成员,将会产生两个

不同的A的数据成员值

如下(Grandfather对应A,a是其公有数据成员,Father1,Father2对应B、C,son对应D的对象,)

可以看到有两个不一样的a存在,说明在赋值过程中Father1,Father2分别调用Grandfather产生两个a

从其运行结果也可以看出来

如果son对象仅想产生一个数据成员a,则必须对Grandfather进行虚继承

//Test1.h
#include<iostream>
using namespace std;
class Grandfather
{
public:
    int a;
    Grandfather(int _a):a(_a)
    {
        cout<<"Grandfather was built. "<<endl;
    }
    ~Grandfather(){cout<<"Grandfather was free. "<<endl;}
};
class Father1 : public virtual Grandfather
{
public:
    int n;
    Father1(int _a) : n(_a),Grandfather(_a)
    {
        cout<<"Father1 was built. "<<endl;
    }
    ~Father1(){cout<<"Father1 was free. "<<endl;}
};
class Father2 : virtual public Grandfather //virtual写在public前后都可以
{
public:
    int n;
    Father2(int _a) : n(_a),Grandfather(_a)
    {
        cout<<"Father2 was built. "<<endl;
    }
    ~Father2(){cout<<"Father2 was free. "<<endl;}
};
class Son : public Father1, public Father2
{
public:
    Son(int _a):Father1(_a),Father2(_a),Grandfather(_a)
    {
        cout<<"Son was built. "<<endl;
    }
    ~Son(){cout<<"Son was free. "<<endl;}
};

虚继承就是在继承符(public、protected、private)前或后加上virtual关键字,被虚继承的类也叫虚基类

在派生类对象的创建中,

首先是虚基类的构造函数并按他们声明顺序构造。

第二批是非虚基类的构造函数按他们声明的顺序调用

第三批是成员对象的构造函数

最后是派生类自己的构造函数。

#include"Test1.h"
void main()
{
    Son son(10);
    son.Father1::n = 1;
    son.Father2::n = 2;//由于在Father1,Father2内均存在公有数据n,在对其赋值时需要加上作用域
    son.Father1::a = 5;
    son.Father2::a = 6;//两次赋值均对一个数据成员操作
}

可以看到两个数据成员的地址相同。

运行结果

析构顺序和构造顺序相反。

原文地址:https://www.cnblogs.com/area-h-p/p/10350517.html

时间: 2024-10-29 01:25:47

钻石(菱形)继承和虚基类的相关文章

C++ Primer学习笔记32_面向对象编程(3)--继承(三):多重继承、虚继承与虚基类

C++ Primer学习笔记32_面向对象编程(3)--继承(三):多重继承.虚继承与虚基类 一.多重继承 在C++语言中,一个派生类可以从一个基类派生,称为单继承:也可以从多个基类派生,称为多继承. 多重继承--一个派生类可以有多个基类 class <派生类名> : <继承方式1> <基类名1>,<继承方式2> <基类名2>,... { <派生类新定义成员> }; 可见,多继承与单继承的区别从定义格式上看,主要是多继承的基类多于一个

C++虚继承和虚基类

看如下代码: 1 #include <iostream> 2 3 using namespace std; 4 5 class A { 6 public: 7 A() {}; 8 9 protected: 10 int m_a; 11 }; 12 13 class B : public A 14 { 15 public: 16 B(){}; 17 18 protected: 19 int m_b; 20 }; 21 22 class C : public A 23 { 24 public: 2

【C++】继承(虚基类)

类的继承与派生 面向对象技术强调软件的可重用性,这种重用性通过继承机制来实现.而在类的继承过程中,被重用的原有类称为基类,新创建的类称为派生类.派生类定义语法格式如下: class <派生类名> : <继承方式> <基类名1>, <继承方式> <基类名2> ...... { <派生类成员的定义>; } 继承方式控制着派生类成员以及派生类对象如何访问从基类继承来的成员:“:”后只有一个基类为单继承,有多个基类为多继承. 派生类的构造函数

类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类

 常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换. 通过函数的构造函数实现转换. 类类转换函数,当构造函数不能将类型转换成基本类型时.所以就有了类类转换函数,通过这种方式. 案例: #include <iostream> class fushu { public: //通过加explicit的这种方式避免隐式转换,避免引发歧义 explicit fushu(int num) { x = num; y = num; } void print() { std::cou

C++中的 虚函数 纯虚函数 虚基类(virtual)

前言:需要了解三者的区别,必须要掌握多态的三个必要条件: 继承 重载 父类指针指向子类对象. 虚函数 纯虚函数 虚基类三者区别 1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的. 2.纯虚函数是用来定义接口的,也就是基类中定义一个纯虚函数,基类不用实现,让子类来实现. 3.虚基类是用来在多继承中,比如菱形继承中,如果两个父类继承自同一个类,就只实例化一个父类 ①虚函数第一个是没有使用多态(只用继承)的一般实现方式: class A { public:

C++的虚基类知识点

当在多条继承路径上有一个公共的基类,在这些路径的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类. class x1:virtual public x{//... ...};class x2:virtual public x{//... ...};虚基类的初始化 虚基类(虚拟继承)的初始化与一般多继承的初始化在语法上是一样的,但构造函数的调用次序不同. 派生类的构造函数的调用次序有三个原则:(1)虚基类的构造函数在非虚基类之

重拾C++之虚函数和虚基类以及抽象类

一.引言 好久没接触过C++了,今天突然要用一点感觉号蛋疼,用惯了python感觉C++一点都不会了. 声明了一个类的对象居然用这种方法,脑子绝对是被驴(python)踢了 class A{  ...  }  a=A();//尼玛这都能行,被踢大了 二.虚函数和一般函数 虚函数就是加了vritual关键字的函数,引入虚函数的目的是为了实现多态性(在此为运行时的多态性),即可以通过父类的指针调用子类的对象,从而产生不同的效果.     virtual void show(){         co

C++虚基类详解(转)

我们知道,如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员.在引用这些同名的成员时,必须在派生类对象名后增加直接基类名,以避免产生二义性,使其惟一地标识一个成员,如:    c1.A::display( ) 在一个类中保留间接共同基类的多份同名成员,虽然有时是有必要的,可以在不同的数据成员中分别存放不同的数据,也可以通过构造函数分别对它们进行初始化.但在大多数情况下,这种现象是人们不希望出现的.因为保留多份数据成员的拷贝

C++ 类的继承五(多继承的二义性--虚基类)

//多继承的二义性--虚基类(了解为主) #include<iostream> using namespace std; /* 多继承在现在的项目开发中一般不使用,他会增加项目的复杂度 */ class Point{ public: Point(){ x = 1; y = 1; } int x; int y; }; class PointA :virtual public Point{ public: PointA(){ a = 2; } int a; }; class PointB :vir