C++ 学习笔记 1 - Virtual

三种主要用法:

1. 多态

- 解决的问题

在面向对象的编程中,首先会针对数据进行抽象(确定基类)和继承(确定派生类),构成类层次。这个类层次的使用者在使用它们的时候,如果仍然在需要基类的时候写针对基类的代码,在需要派生类的时候写针对派生类的代码,就等于类层次完全暴露在使用者面前。如果这个类层次有任何的改变(增加了新类),都需要使用者“知道”(针对新类写代码)。这样就增加了类层次与其使用者之间的耦合,有人把这种情况列为程序中的“bad smell”之一。

- 如何实现

编译器是如何针对虚函数产生可以再运行时刻确定被调用函数的代码呢?也就是说,虚函数实际上是如何被编译器处理的呢?

我所说的“标准”方式,也就是所谓的“VTABLE”机制。编译器发现一个类中有被声明为virtual的函数,就会为其搞一个虚函数表,也就是VTABLE。

VTABLE实际上是一个函数指针的数组,每个虚函数占用这个数组的一个slot。一个类只有一个VTABLE,不管它有多少个实例。派生类有自己的VTABLE,但是派生类的VTABLE与基类的VTABLE有相同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。

在创建类实例的时候,编译器还会在每个实例的内存布局中增加一个vptr字段,该字段指向本类的VTABLE

因为派生类和基类的foo()函数具有相同的VTABLE索引,而他们的vptr又指向不同的VTABLE,因此通过这样的方法可以在运行时刻决定调用哪个foo()函数。

- 纯虚函数

一个函数声明为纯虚后,纯虚函数的意思是:我是一个抽象类不要把我实例化!纯虚函数用来规范派生类的行为,实际上就是所谓的“接口”。它告诉使用者,我的派生类都会有这个函数。

- 答疑

overload:重载 是指编写一个与已有函数同名但是参数表不同的函数

override: override是指派生类重写基类的虚函数

2. 虚继承:解决数据冗余

3. 虚析构:可以防止内存泄漏

例如: virtual ~ClassA() = 0;

当一个类打算被用作其它类的基类时,它的析构函数必须是虚的.

int main()
{
   Base *basePtr = new Child();
   //delete basePtr;
   return 0;
}

case 1: //delete basePtr;  && 非virtual 析构

        construct Base ...
        construct Child ...

case 2: delete basePtr; &&  非virtual 析构

        construct Base ...
        construct Child ...
        release Base ...

case 3: delete basePtr; &&  virtual 析构

        construct Base ...
        construct Child ...
        release Child ...
        release Base ...

Reference: C++中的虚函数(virtual function)-太平洋电脑网 (pconline.com.cn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值