vtable的c ++思想中的多态性(动态绑定)

Posted

技术标签:

【中文标题】vtable的c ++思想中的多态性(动态绑定)【英文标题】:Polymorphism in c++ idea of vtable (dynamic binding) 【发布时间】:2016-02-02 10:49:12 【问题描述】:

我正在考虑 C++ 中的多态机制,但我无法理解一件事。这里我有一段非常简单的代码,只有一个类:

#include <iostream>

using namespace std;

class A

public:
    int x;
    void fun1();
    double fun2(int, char*);
    void fun3(double, float[]);
;

int main()

    cout << sizeof(A) << endl;
return 0;

在控制台上将打印 int 对象 (x) 的大小 - 很明显。如果我通过添加关键字 virtual 修改我的类,则大小将会改变,因为编译器正在添加指向虚拟函数数组(vtable)的指针。但是,在编写具有完全不同签名的新虚拟方法的声明时,我的类的大小怎么可能不会改变呢?我的意思是:

void (*(tab[100]) )(int, double, char*);

这是一个数组的定义,它必须具有带有签名的函数地址:

void fun(int, double, char*);

而且只有这种类型的函数可以添加到这个数组中,那么为什么无论哪种类型的虚方法类都只包含一个指向一个虚数组的指针呢?我的逻辑哪里出错了?

【问题讨论】:

澄清一下:vtable 不是每个类实例的一部分;它就像一个静态成员,只存在一次。 【参考方案1】:

可能是useful:

虚拟桌子其实很简单,虽然用文字来描述有点复杂。首先,每个使用虚函数的类(或派生自使用虚函数的类)都有自己的虚表。该表只是编译器在编译时设置的静态数组。一个虚拟表包含一个条目,对应于类对象可以调用的每个虚拟函数。此表中的每个条目只是一个函数指针,指向该类可访问的最衍生函数

【讨论】:

【参考方案2】:

第一件事 - 标准并没有说什么关于虚拟表。它只谈论虚函数和多态性。每个编译器都可以以它喜欢的任何方式实现此功能。

虚表只是虚函数的常用实现,不是强制性的,每个编译器的实现都不一样。

最后,在我的 Visual Studio 2015 上,这个:

class A1 
    int x;
    void doIT()
;

class A2 
    int x;
    virtual void doIT()
;

constexpr int size = sizeof(A1);
constexpr int size2 = sizeof(A2);

使size 4 个字节,但size2 12 个字节,这打破了你的假设。 同样,GCC、Clang 甚至 C++/CLI 可能有不同的行为,并产生不同的大小。

【讨论】:

以上是关于vtable的c ++思想中的多态性(动态绑定)的主要内容,如果未能解决你的问题,请参考以下文章

利用虚函数实现多态的方式:动态绑定

Java编程思想重点

面向对象

Java编程思想重点笔记

java 编程思想笔记——多态

C++Primer 第十五章