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

类的继承与派生

  面向对象技术强调软件的可重用性,这种重用性通过继承机制来实现。而在类的继承过程中,被重用的原有类称为基类,新创建的类称为派生类。派生类定义语法格式如下:

    class <派生类名> : <继承方式> <基类名1>, <继承方式> <基类名2> ......    {      <派生类成员的定义>;    }

  继承方式控制着派生类成员以及派生类对象如何访问从基类继承来的成员;“:”后只有一个基类为单继承,有多个基类为多继承。

派生类的构造函数和析构函数

  由于基类的构造函数和析构函数不能被继承,在派生类中,如果对派生类新增的成员进行初始化,就必须为派生类添加新的构造函数。

构造函数

  派生类从基类继承了非私有成员函数和数据成员,但在创建派生类对象时,系统执行派生类的构造函数,而不会自动执行基类的构造函数。如果基类的构造函数包含对基类数据的初始化,那么在设计派生类的构造函数时,还应为初始化基类数据成员提供参数,所有这些参数在派生类的构造函数中都以初始化列表的形式提供,语法格式如下:  

    <派生类名>(<形参表>) : <基类名1>(<形参表1>), <基类名2>(<形参表2>) ......    {      <派生类新增数据成员的初始化>;    }

  在创建派生类对象时,系统是使用派生类的构造函数参数表所提供的参数,首先去调用基类的构造函数。

析构函数

  在执行派生类的析构函数时,基类的析构函数也将被自动调用,它们的顺序恰好与派生类的构造函数的调用顺序相反,先派生类的析构函数,后基类的析构函数。

虚基类

  多重继承可能会带来多义性问题,C++中的作用域分辨符和虚基类技术都可解决此问题,但最好尽量不要使用多继承。

  作用域分辨符就是类域标记"::",语法格式如下:

    <派生类对象名>.<基类名>::<成员函数名>(<参数表>);

  虚基类是消除多义性的另一种简单而有效的方法。对于可能在不同派生路径中产生多个成员副本的基类,可以将其设为虚基类,这样在内存中,它的数据成员就只有一个副本,成员函数也只有一个映射,从而解决了同名成员函数的唯一标识问题。

  虚基类有关键字virtual 标识,语法格式如下:

    class <派生类名>:virtual <继承方式> <基类名>

  使用作用域分辨符时,基类的成员在内存中有多个副本,通过制定基类名来唯一标识使用副本,这样可以存放不同的数据,进行不同的操作。使用虚基类技术,是基类的成员在内存中只有一个副本。相比之下,前者可以容纳更多的数据,后者形式更加简洁,更节省内存空间。可根据实际情况选择合适的方式。

时间: 2024-10-09 15:04:28

【C++】继承(虚基类)的相关文章

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

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

虚基类的用法

1 #include <iostream> 2 3 using namespace std; 4 5 class A 6 { 7 private: 8 int a; 9 public: 10 A(int x):a(x){} 11 void show() const 12 { 13 cout<<"a: "<<a<<endl; 14 } 15 ~A(){} 16 }; 17 class B:virtual public A //定义虚基类的用

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

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

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

虚基类 继承中的构造函数

/* *Copyright (c)2014,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:d.cpp *作 者:张旺华 *完成日期:2015年6月1日 *版 本 号:v1.0 */ #include <iostream> using namespace std; class Base { public: Base(char i) { cout<<"Base constructor. --"<<i<<

C++ 虚基类 派生与继承

在学习设计模式时我就有一个疑问,关联和继承除了用法上的区别,好像在内存上并没有什么区别,继承也是父类作为了子类的元素(内存上),关联也是这样.而且关联好像更占内存一些.这就是设计模式里问题了“依赖倒转原则”. 继承分为public继承,protect继承,private继承 public:父类中的public,protected成员到了派生类中属性不变. protected:父类中的public,protected成员到了派生类中,都变为protected成员. private:父类中的publ

第十二周 阅读程序 虚基类 中的继承

/* *Copyright (c)2014,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:d.cpp *作 者:张旺华 *完成日期:2015年6月1日 *版 本 号:v1.0 */ #include <iostream> using namespace std; class Base { public: Base(char i) { cout<<"Base constructor. --"<<i<<

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

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

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

钻石(菱形)继承 如图,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进