虚拟表C ++

时间:2010-01-31 21:45:36

标签: c++ derived-class virtual-functions vtable

我读了很多人写的“一个虚拟表存在于一个已经声明了虚函数的类中。”

我的问题是,vtable是否仅存在于具有虚函数的类中,还是存在于从该类派生的类中。

e.g

class Base{
    public:
        virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
    public:
        void print(){cout<<"Derived print\n";}
};

//From main.cpp 
Base* b = new Derived;
b->print();

问题:如果没有派生类的vtable,那么输出就不会是“派生打印”。所以IMO存在一个vtable,用于任何已声明虚函数的类,也存在于从该类继承的类中。这是对的吗?

4 个答案:

答案 0 :(得分:19)

至于只考虑特定于虚函数的功能,在vtable实现的传统方法中,派生类需要单独版本的vtable 当且仅当派生类重写至少一个虚函数。在您的示例中,Derived会覆盖虚函数print。由于Derived拥有自己的print版本,因此Derived vtable中的相应条目与Base vtable中的条目不同。这通常需要Derived单独的vtable。

如果Derived根本没有覆盖任何东西,那么正式它仍然是一个单独的多态类,但为了使其虚函数正常工作,我们可以简单地重用Base vtable for { {1}}也是。因此,从技术上讲,Derived不需要单独的vtable。

然而,在实际实现中,我们通常称为“vtable”的数据结构通常还包含一些其他类特定信息。额外信息是特定于类的,大多数情况下,即使它们使用相同的虚拟函数集,也无法在层次结构中的不同类之间共享vtable。例如,在一些实现中,存储在每个多态对象中的vtable指针指向还存储关于该类的所谓“RTTI信息”的数据结构。因此,在大多数(如果不是全部)实际实现中,每个多态类都有自己的vtable,即使这些表中存储的虚函数指针恰好相同。

答案 1 :(得分:3)

是的,您的理解是正确的。任何具有任何虚函数的基类的类都有一个vtable。

答案 2 :(得分:3)

是的,这是真的。实际上,给定基数的定义:

class derived:public base{
public:
 void print(){cout<<"derived print\n";}
};

完全等同于:

class derived:public base{
public:
 virtual void print(){cout<<"derived print\n";}
};

...因为您已经在基础中将print定义为虚拟。

我希望编译器强制执行......

答案 3 :(得分:2)

是的,那是真的。类继承其基类中的所有数据成员,包括vtable。但是,相应地调整vtable条目(例如,如果类重写基类虚方法,则vtable中的相应条目必须指向其自己的实现)。

但请记住,'vtable'的概念是每个编译器都使用的常用做法,但它不是强制性的,也不是标准化的。

相关问题