首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么“虚拟”继承不是默认行为?

为什么“虚拟”继承不是默认行为?
EN

Stack Overflow用户
提问于 2014-02-28 08:49:42
回答 2查看 529关注 0票数 3

我理解在从基类派生时使用virtual关键字的要求,以避免菱形继承相关的歧义问题。

但是,我的问题是,当派生类时,这为什么不是C++中的默认行为,无论菱形问题是否存在?

在钻石继承不存在的情况下,使用'virtual‘关键字有什么’害处‘吗?

EN

回答 2

Stack Overflow用户

发布于 2014-02-28 08:59:26

虚拟继承有一个运行时开销:转换指针需要一个只在运行时知道的调整,而对于非虚拟继承,它可以在编译时知道。它还可以使类的派生更加复杂,因为虚拟基类是由最终的派生类初始化的,而不是(必然)直接从它们继承的类。

因此,只有当您特别需要菱形结构时才需要它;必须记住指定非虚拟继承以避免隐藏的开销,这将是一件痛苦的事情。C++通常遵循的原则是,你不应该为你不需要的功能付费。

票数 6
EN

Stack Overflow用户

发布于 2014-02-28 08:55:50

有一个开销,试一下:

代码语言:javascript
运行
复制
#include <iostream>

struct Foo {
    int a;
};

struct Bar : Foo {
    int b;
};

struct Baz : virtual Foo {
    int b;
};

int main() {
    std::cout << sizeof(Foo) << " ";
    std::cout << sizeof(Bar) << " ";
    std::cout << sizeof(Baz) << "\n";
}

在我的实现中,我得到了4 8 16。虚拟继承需要vptr或等效机制,因为类Baz不知道Foo基类子对象相对于Baz基类子对象将出现在什么偏移处。这取决于派生次数最多的类型是否也通过另一个路由继承Foo

由于vptr在那里,人们还期望在某些情况下将使用它,这是更多的开销:-)即,为了经由Baz*Baz&访问Foo::a,需要一个或多个附加的间接地址。如果编译器以某种方式知道引用对象的派生类型,它可能会选择避免这种情况。

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

https://stackoverflow.com/questions/22083996

复制
相关文章

相似问题

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