C++ 虚基类 派生与继承

在学习设计模式时我就有一个疑问,关联和继承除了用法上的区别,好像在内存上并没有什么区别,继承也是父类作为了子类的元素(内存上),关联也是这样。而且关联好像更占内存一些。这就是设计模式里问题了“依赖倒转原则”。

继承分为public继承,protect继承,private继承

public:父类中的public,protected成员到了派生类中属性不变。

protected:父类中的public,protected成员到了派生类中,都变为protected成员。

private:父类中的public,protected成员到了派生类中,都变成了private成员。

特别注意:父类中的private成员是不会被继承到子类中的(这也是关联和继承的一个区别)。

特别注意:还有一种继承被称为虚继承

详细回顾一下虚继承:

虚继承的形式:

class 派生类:virtual 基类1,virtual 基类2, virtual 基类3……

{
};

构造函数过程:

首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;

执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;

执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;

执行派生类自己的构造函数;

析构以与构造相反的顺序执行;

虚继承的实质是,在多继承中,派生类的基类中如果有过个基类继承至同一基类,那么这几个基类肯定含有这同一基类的拷贝(各自各一份),所以在派生类中如果想使用,就必须加上作用域分辨符来唯一识别。这时如果另这些基类继承时用上虚基类就可以解决这个问题了。我们可以将共同继承的基类,设为虚基类,这时从不同路径继承过来的同名的数据成员在内存中就只有一份拷贝, 同名函数也只有一个映射。

 1 #include<iostream>
 2
 3 using namespace std;
 4
 5 class Base
 6 {
 7 private:
 8     int val;
 9 public:
10     Base(){ cout << "Base无参构造函数" << endl; };
11     Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
12     void print(){ cout << "val = "<<val << endl; }
13 };
14
15 class Sub1 :virtual public Base
16 {
17 public :
18     Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
19 };
20
21 class Sub2 :virtual public Base
22 {
23 public:
24     Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
25 };
26
27 class Child :public Sub1, public Sub2
28 {
29 public :
30     Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
31 };
32
33 int main()
34 {
35     Child child(3);
36     child.print();
37 }

输出结果:

Base无参构造函数
Sub1含参构造函数
Sub2含参构造函数
Child含参构造函数
val = -858993460
Press any key to continue . . .

可见Sub1,和Sub2构造函数并没有执行Base的构造函数,虚继承的构造函数是这样的,先执行虚基类的无参构造函数,然后在执行Sub1的构造函数,在执行Sub2的构造函数,在执行Child的构造函数,并且在执行Sub1和Sub2的构造函数时并不再执行Base的构造函数。

如果不用虚继承的访问方式:

 1 #include<iostream>
 2
 3 using namespace std;
 4
 5 class Base
 6 {
 7 private:
 8     int val;
 9 public:
10     Base(){ cout << "Base无参构造函数" << endl; };
11     Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
12     void print(){ cout << "val = "<<val << endl; }
13 };
14
15 class Sub1 :public Base
16 {
17 public :
18     Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
19 };
20
21 class Sub2 :public Base
22 {
23 public:
24     Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
25 };
26
27 class Child :public Sub1, public Sub2
28 {
29 public :
30     Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
31 };
32
33 int main()
34 {
35     Child child(3);
36
37     //child.print()   //非法的访问
38
39     child.Sub1::print();
40     child.Sub2::print();
41 }

结果:

Base有参构造函数
Sub1含参构造函数
Base有参构造函数
Sub2含参构造函数
Child含参构造函数
val = 3
val = 3
Press any key to continue . . .

时间: 2024-11-03 22:40:20

C++ 虚基类 派生与继承的相关文章

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

/* *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++的虚基类知识点

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

第十二周 阅读项目 (4)虚基类多重继承数据理解

<span style="font-size:18px;">/* *Copyright (c)2014,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:d.cpp *作 者:张旺华 *完成日期:2015年6月1日 *版 本 号:v1.0 */ #include<iostream> using namespace std; class A { public: int n; }; class B:virtual public A

C++:虚基类

4.4.3 虚基类1.没什么要引入虚基类 如果一个类有多个直接基类,而这些直接基类又有一个共同的基类,则在最底层的派生类中会保留这个间接的共同基类数据成员的多分同名成员.在访问这些同名的成员时,必须在派生类对象后增加直接基类名,使其惟一地标识一个成员,以免产生二义性. //例 4.15 虚基类的引例 #include<iostream> using namespace std; class Base{ //声明类Base1和类Base2的共同的基类Base public: Base() { a

C++语言笔记系列之十七——虚基类

1.虚基类 考虑这样一种情况:当某个类的部分或者全部直接基类是另一个共同基类派生而来,这些直接基类从上一级基类继承而来的成员就一定拥有相同的名称,这样就会产生二义性问题. 解决办法:当派生类和直接基类产生了二义性问题-->加类的作用域. 当派生类和间接基类产生了二义性问题-->虚基类. 2.虚基类的说明: class 派生类名:virtual 访问权限 基类名 {派生类定义}; 注意:在定义派生类时将需要继承的基类进行虚化声明,虚基类的说明在派生类的定义中完成. 作用:将基类说明为虚基类之后,

基类派生类

看了c#的教程,也上网络上搜索基类与派生类的概念,一直没有一个很明确的定义.弄得偶一直很迷糊,现在搜索到c++的教程里倒是有比较明确的说明,特意贴在这里,帮助自己理解. 继承机制提供了无限重复利用程序资源的一种途径. 继承使得我们得以用一种简单的方式来定义新类.如果我们定义了一个哺乳动物类,包括哺乳动物的一些普通属性和方法,然后再定义一个狗类, 有没有必要重头开始定义呢?实际上这是没有必要的,因为狗是哺乳动物的一种特殊动物,定义狗类可以沿用哺乳动物类的所需的属性和方法,只需加上狗的颜色属性和狗尾

虚基类

class B { public: int b; }; class C1 :virtual public B { public: int c1; }; class C2 :virtual public B { public: int c2; }; class D :public C1, public C2 { public: int d; }; int main() { cout << sizeof(D ) << endl;     //24 B b; D d; system( &

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

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

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

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