C++学习之路——继承机制

1、继承

C++的访问控制方式有三种:public(公有继承)、protected(保护继承)和private(私有继承)。

C++派生类继承了基类的所有数据类型和除了构造函数和析构函数的所有成员函数。

 基类的public基类的protected基类的private
公有继承publicprotected不可访问
保护继承protectedprotected不可访问
私有继承privateprivate不可访问
2、重写、覆盖和隐藏

成员函数被重载的特征:

  • 函数名相同
  • 在同一个类体
  • 参数个数或者类型不同
  • virtual关键字可有可无
成员函数被覆盖的特征:
  • 函数名相同
  • 不同的类体(基类和派生类)
  • 参数个数和类型必须相同
  • 必须有virtual关键字
C++的隐藏机制:
对于在不同作用域声明的标识符,可见性的原则是:如果存在两个或多个具有包含关系的作用域,外层声明了一个标识符,而内层没有再次声明该标识符,则该外层标识符在内层仍可见;如果内层声明了该标识符,则外层标识符被隐藏,内层作用域只可见内层声明的标识符。
对于成员函数,如果派生类中声明了与基类同名的成员函数,那么即使参数不同,从基类继承的所有该同名函数的重载形式都将被隐藏。
多继承派生类会隐藏所有基类的同名函数的所有重载形式。

外层成员函数仍可访问,但要通过“类对象.基类名::成员函数”的形式,或者”类指针->基类名::成员函数“的形式。

virtual关键字和隐藏机制的关系:

通过virtual关键字被继承的类称为虚基类。


通过以下两个例子对比分析virtual关键字的作用

// Demo7_7.cpp: 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include<iostream>
using namespace std;


class base0 {
public:
int var0 = 3;
void fun0() { cout << "var0 = " <<var0 << "\t member of base0 \t" <<&var0<<endl; }
};
class base1 :public base0 {
public:
int var1;
};
class base2 : public base0 {
public:
int var2;
};
class Derived :public base1, public base2 {
public:
int var;
void fun() { cout << "var = " << var << "\t\t member of Deriverd \t" <<&var<<endl; }
};
int main()
{
Derived d;
Derived *p = &d;


base0 b;


b.base0::var0 = 0;
b.base0::fun0();


d.base1::var1 = 1;
d.base1::fun0();


d.base2::var2 = 2;
d.base2::fun0();


d.var = 4;
d.fun();


b.base0::var0 = 5;
b.base0::fun0();


system("pause");
    return 0;
}

运行结果:


程序结果分析:4个类(base0、base1、base2、Deriverd)各自保存了从类base0继承而来的成员数据和成员函数,即共有四个空间被占用,类base1、base2占用了不同的存储空间。

加上virtual关键字,把base0变为虚基类

// Demo7_7.cpp: 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include<iostream>
using namespace std;


class base0 {
public:
int var0 = 3;
void fun0() { cout << "var0 = " <<var0 << "\t member of base0 \t" <<&var0<<endl; }
};
class base1 :virtual public base0 {
public:
int var1;
};
class base2 :virtual public base0 {
public:
int var2;
};
class Derived :public base1, public base2 {
public:
int var;
void fun() { cout << "var = " << var << "\t\t member of Deriverd \t" <<&var<<endl; }
};
int main()
{
Derived d;
Derived *p = &d;


base0 b;


b.base0::var0 = 0;
b.base0::fun0();


d.base1::var1 = 1;
d.base1::fun0();


d.base2::var2 = 2;
d.base2::fun0();


d.var = 4;
d.fun();


b.base0::var0 = 5;
b.base0::fun0();


system("pause");
    return 0;
}


运行结果:


结果分析:

可以看到此时对类base1、base2成员的访问在同一地址,说明此时base1、base2共同使用同一空间,即对虚基类的继承,所有的类共同维护同一副本。此时共有三个副本,base0、base1和base2共同维护的一个副本和Deveried的副本。


总结:virtual关键字使继承虚基类的类共同维护同一副本,减少了程序对空间的开支,但是同时也减少了能够存储的数据量。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值