`
benson76
  • 浏览: 34128 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[转] c++ 虚函数的实现机制:笔记

    博客分类:
  • C++
 
阅读更多

http://blog.csdn.net/jiangnanyouzi/article/details/3720807

 

1、c++实现多态的方法

其实很多人都知道,虚函数在c++中的实现机制就是用虚表和虚指针,但是具体是怎样的呢?从more effecive c++其中一篇文章里面可以知道:是每个类用了一个虚表,每个类的对象用了一个虚指针。具体的用法如下:

class A
{
public:
    virtual void f();
    virtual void g();
private:
    int a
};

class B : public A
{
public:
    void g();
private:
    int b;
};

//A,B的实现省略

因为A有virtual void f(),和g(),所以编译器为A类准备了一个虚表vtableA,内容如下:

A::f 的地址
A::g 的地址

B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:

A::f 的地址
B::g 的地址

注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。

然后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局如下:

vptr : 指向B的虚表vtableB
int a: 继承A的成员
int b: B成员

当如下语句的时候:
A *pa = &bB;

pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)

那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。

这一项放的是B::g()的入口地址,则就实现了多态。(注意bB的vptr指向的是B的虚表vtableB)

另外要注意的是,如上的实现并不是唯一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。我以上的结果是根据g++ 4.3.4经过反汇编分析出来的。

2、两种多态实现机制及其优缺点

除了c++的这种多态的实现机制之外,还有另外一种实现机制,也是查表,不过是按名称查表,是smalltalk等语言的实现机制。这两种方法的优缺点如下:

(1)、按照绝对位置查表,这种方法由于编译阶段已经做好了索引和表项(如上面的call *(pa->vptr[1]) ),所以运行速度比较快;缺点是:当A的virtual成员比较多(比如1000个),而B重写的成员比较少(比如2个),这种时候,B的vtableB的剩下的998个表项都是放A中的virtual成员函数的指针,如果这个派生体系比较大的时候,就浪费了很多的空间。

比如:GUI库,以MFC库为例,MFC有很多类,都是一个继承体系;而且很多时候每个类只是1,2个成员函数需要在派生类重写,如果用C++的虚函数机制,每个类有一个虚表,每个表里面有大量的重复,就会造成空间利用率不高。于是MFC的消息映射机制不用虚函数,而用第二种方法来实现多态,那就是:

(2)、按照函数名称查表,这种方案可以避免如上的问题;但是由于要比较名称,有时候要遍历所有的继承结构,时间效率性能不是很高。(关于MFC的消息映射的实现,看下一篇文章)

3、总结:

如果继承体系的基类的virtual成员不多,而且在派生类要重写的部分占了其中的大多数时候,用C++的虚函数机制是比较好的;

但是如果继承体系的基类的virtual成员很多,或者是继承体系比较庞大的时候,而且派生类中需要重写的部分比较少,那就用名称查找表,这样效率会高一些,很多的GUI库都是这样的,比如MFC,QT

PS. 其实,自从计算机出现之后,时间和空间就成了永恒的主题,因为两者在98%的情况下都无法协调,此长彼消;这个就是计算机科学中的根本瓶颈之所在。软件科学和算法的发展,就看能不能突破这对时空权衡了。呵呵

何止计算机科学如此,整个宇宙又何尝不是如此呢?最基本的宇宙之谜,还是时间和空间~

分享到:
评论

相关推荐

    C++虚函数和多态学习笔记

    ### C++虚函数和多态学习笔记 #### 一、虚函数与多态的基本概念 在C++中,虚函数是实现多态的一种机制。多态是指同一个接口(方法名)可以有不同的行为表现,即“一种接口,多种方法”。通过虚函数,我们可以实现...

    千锋C++笔记.zip

    7. **多态**:多态分为静态多态(函数重载、运算符重载)和动态多态(虚函数、纯虚函数、抽象类)。动态多态主要体现在运行时,通过指针或引用调用父类方法实现不同子类的特定实现。 8. **模板**:C++的模板功能...

    c++学习笔记.pdf

    虚函数允许基类指针或引用调用派生类对象中的重写版本函数,这是实现运行时多态的关键机制。基类通过维护一个虚函数表(虚表),其中包含了指向虚函数的指针,每个派生类可以重写这些虚函数。当通过基类的指针调用虚...

    C++学习笔记(13)——利用对象、引用、指针调用虚函数.pdf

    在C++编程语言中,虚函数是实现多态性的重要机制。本文主要探讨了如何通过对象、引用和指针调用虚函数,并深入解析了虚函数的实现原理和相关知识点。 首先,虚函数的主要作用是允许基类指针或引用调用派生类中的...

    C++笔记.rar C++笔记.rar

    多态性主要通过虚函数和纯虚函数实现,允许不同的子类对同一函数有不同的实现。 4. **模板**:C++的模板机制使得我们可以创建泛型代码,不仅可以用在函数上,也可以用于定义泛型类,增加了代码的灵活性和可重用性。...

    C++学习笔记(13)——利用对象、引用、指针调用虚函数.docx

    在C++中,虚函数是实现多态性的重要机制,特别是在面向对象编程中。当一个类含有虚函数时,编译器会为该类创建一个虚拟表(VTABLE),其中包含了类中所有虚函数的地址。这个VTABLE使得在运行时能够根据对象的实际...

    Effective C++学习笔记

    - 在C++中,虚函数是实现多态性的关键。它们允许通过基类指针调用派生类的成员函数,即使指针实际指向的是派生类的对象。例如,如果一个基类`Base`有一个纯虚函数,派生类`Derived`必须实现这个函数。如果在基类的...

    C语言和C++Builder学习笔记.rar_C++笔记_c++学习笔记_c/C++_学习笔记_编程语言

    3. **虚函数与纯虚函数**:实现多态性,为接口设计提供支持。 4. **标准模板库(STL)**:包括容器(如vector、list、set等)、迭代器、算法和函数对象,极大地增强了代码的可读性和效率。 5. **MFC或VCL框架**:...

    面向对象程序设计C++听课笔记

    4. 虚函数与抽象类:虚函数实现多态,使得基类指针可以调用派生类的函数;纯虚函数定义抽象类,不能实例化。 四、C++的类和对象 1. 类的声明与定义:声明类的结构,定义类的成员函数。 2. 对象的创建与使用:通过...

    达内C-C++基础学习笔记

    多态是指同一消息可以有不同的行为,这在运行时通过虚函数和抽象类实现。 10. **模板**:C++的模板机制允许创建泛型代码,可用于不同类型的数据,增加了代码的通用性。 11. **异常处理**:C++的异常处理机制提供了...

    《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

    虚函数表(vtable)是C++实现动态绑定的关键机制,它允许子类重写基类的方法并保持向上兼容。理解vptr和vtable的工作原理对于调试和优化代码至关重要。 模板是C++的另一个强大特性,它提供了泛型编程的能力。模板...

    C++快速复习笔记.rar

    3. 多态:通过虚函数和抽象类实现,允许子类重写父类的方法,提供不同的实现。 三、模板 C++中的模板允许我们编写泛型代码,可以用于处理不同数据类型。有函数模板和类模板两种,它们能提高代码的灵活性和可复用性...

    C++进阶笔记源码

    笔记可能会深入讲解如何设计和实现类、接口以及如何利用虚函数和纯虚函数实现多态性。 2. **STL(Standard Template Library)**:STL是C++标准库的一部分,提供了容器(如vector、list、map)、算法和迭代器等工具...

    C++ Polymorphism 笔记 1

    在C++中,多态性通常通过虚函数机制来实现。 ##### 3.1 虚函数的基本用法 虚函数必须在基类中声明为 virtual,这样派生类就可以覆盖该函数,并且当基类指针指向派生类对象时,可以调用派生类的版本。例如,在上面...

    C++读书笔记

    5. **多态**:多态是同一消息可以有不同的响应,这在C++中通过虚函数和纯虚函数实现。多态性增强了程序的灵活性和可扩展性。 6. **模板**:C++模板允许创建泛型函数和类,这样可以在不同数据类型上复用相同的代码。...

    C++ 基础教程笔记

    多态是指同一种行为在不同的对象上表现出不同的效果,这主要通过虚函数和纯虚函数来实现。 七、模板 模板是C++中的一种泛型编程工具,可以创建不依赖具体类型的函数或类。模板可以用于创建泛型算法,提高代码的可...

    Effective_C++3 学习笔记.pdf.rar

    10. **多态与继承**:笔记会探讨虚函数、纯虚函数、抽象类和接口,以及动态绑定和静态绑定的概念,帮助理解面向对象设计的核心。 11. **C++11新特性**:第三版涵盖了C++11标准引入的新特性,如lambda表达式、右值...

    钱能的C++笔记,绝对值的珍藏.rar

    同时,继承和多态性是面向对象编程的重要特性,钱能的笔记中会解释如何实现类之间的层次关系,以及虚函数和纯虚函数在多态中的作用。 此外,C++还支持异常处理,这是一项用于错误处理的机制。笔记可能会介绍try、...

Global site tag (gtag.js) - Google Analytics