首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++继承/VTable问题

C++继承/VTable问题
EN

Stack Overflow用户
提问于 2009-09-05 15:53:40
回答 4查看 2.7K关注 0票数 10

Update:用一个直接向上的方法调用示例替换析构函数示例。

嗨,

如果我有以下代码:

代码语言:javascript
复制
class a
{
public:
    virtual void func0(); // a has a VTable now
    void func1();
};
class b : public a
{
public:
    void func0() { a::func0(); }
    void func2();
};

  1. 在B区有VTable吗?B没有虚拟函数,而是从b::func0()
  2. Does func1调用a::VTable 0()?它不是虚拟的。
  3. func2驻留在VTable中吗?如果在b::VTable 0()?

中没有a::VTable 0()调用,那么对上述问题的回答会有所不同吗?

谢谢

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-09-05 16:04:57

如果您声明了虚拟函数,那么还应该声明您的析构函数虚拟;-)。

  1. B有一个虚拟表,因为它有一个虚拟函数,即func0()。如果您在基类中声明一个函数(包括析构函数)为虚拟函数,那么它的所有派生类都将具有相同签名的虚拟函数。这会让他们有一个vtable。此外,即使您没有在其中声明explicitly.
  2. Non-virtual函数,也可以使用vtable。
  3. 参见2.
  4. No。类的vtable是基于类声明构建的。没有考虑到类函数的主体(更不用说其他功能了)。因此,B有一个vtable,因为它的函数func0()是虚拟的.

还有一个棘手的细节,尽管这不是你问题的要点。您将函数B::func0()声明为内联函数。在gcc编译器中,如果一个虚拟函数是内联声明的,它就会将它的插槽保留在虚拟表中,该槽指向为该内联函数发出的一个特殊函数(这意味着它的地址,这使得内联发出)。这意味着函数是否是内联函数并不影响vtable中插槽的数量及其对类的必要性。

票数 19
EN

Stack Overflow用户

发布于 2009-09-05 16:01:26

是的,因为它的基类有一个;而且它的析构函数是虚拟的(即使您没有声明它是虚拟的),因为基类的析构函数是virtual.

  • No

  • No.

  • No.实际上,我认为当前代码是不合法的:编译器将在A析构函数调用B析构函数之后调用它,即使您没有显式调用~A from ~B;所以我认为即使编译器允许您调用~A from ~B,也不应该调用~A析构函数。
票数 5
EN

Stack Overflow用户

发布于 2009-09-05 17:00:45

关于更新的例子:

  1. 是的,b有一个vtable。请注意,b::func0 0()是虚拟的(覆盖a::func0 0()),尽管您没有显式地将它标记为虚拟的。奇怪的C++“漏洞”,我猜。
  2. No。非虚拟函数不驻留在vtable中.
  3. 参见2.
  4. No.您已经重写了一个:func0 0();如果您调用a::func0 0()或not并不重要。

一些额外的注释(编译器依赖的,但这些是相当常见的泛化):

B的每个实例都有一个指向vtable的指针,因为您来自一个具有虚拟functions.

  • This的类,即使您没有定义b::

  • 0(),情况也是如此。在这种情况下,编译器可能有指向a的静态vtable的b点的实例,或者它可能为b创建一个静态vtable,并用指向a.

  • 成员的指针填充它,但它仍然是必需的,这样就可以通过指向.

的指针正确地访问b的实例。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1383650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档