2012-02-04 48 views
1

如果我在C这种情况++项目:C++中的单个虚拟继承编译器优化?

  • 1的基类“基地”只含有纯虚函数
  • 1类“派生”,这从“Base是继承了唯一的类(公共) '

编译器会生成一个VTABLE吗?

似乎没有必要,因为项目只包含一个Base *指针可能指向的(Derived)类,所以这可以解决所有情况下的编译时间。

如果您想为单元测试执行依赖注入,但不希望在生产代码中产生VTABLE查找成本,这很有趣。

+2

编译器不会知道它的基类会在另一个源文件中被继承,所以它可能会添加一个vtable。 – 2012-02-04 12:27:44

+0

噢,对,可以想到,你的答案似乎是正确的。所以看起来我不会使用指向虚拟基类的指针来注册依赖关系,而是给我的测试类使用与生产依赖关系相同的名称,并有条件地在单元测试中编译我的测试类(和我的生产类)。 .. – Sjimmie 2012-02-04 12:38:51

+0

[为什么当派生类不重写虚函数时需要VTABLE?](http://stackoverflow.com/questions/9109662/why-is-a-vtable-required-when-派生类不包含虚拟乐趣) – 2012-02-04 14:55:54

回答

5

我没有硬数据,但我有很好的理由说不,它不会将虚拟呼叫变成静态数据。

  • 通常,编译器只能看到一个编译单元。它不知道只有一个子类,因为五个月后你可以编写另一个子类,编译它,从备份中获得一些古老的目标文件并将它们连接在一起。
  • 虽然链接时间优化确实看到了整个画面,但它们通常在程序的低层次表示上工作。这种表示允许例如内联静态调用,但不代表继承信息(可能除外可选元数据),并已明确显示虚拟调用和vtables。 I 知道 Clang和IIRC的情况gcc的整个程序优化也适用于某些低级IR(GIMPLE?)。
  • 另请注意,通过动态加载,您仍然可以在编译和LTO之后的仍然添加更多的子类。你可能不需要它,但是如果我是一个编译器编写者,我会厌倦添加一个优化,让人们在非常特定的,难以追踪的情况下大量打破虚拟呼叫。
  • 这很难解决 - 如果你不需要虚拟呼叫(例如因为你知道你不需要更多的子类),请不要制造东西virtual。检查你的设计。如果你需要一些多态性,但不是虚拟的全部力量,curiously recurring template pattern可能会有所帮助。
+1

谢谢,你引发了我寻找一个编译时多态解决方案,并有人已经有我认为我可以使用的东西:http://skepticalmethodologist.wordpress.com/2008/07/20/dependency-injection-in-c/ – Sjimmie 2012-02-04 12:55:31

0

编译器根本不必使用基于虚拟功能调度的基于vtable的实现,因此对于您的问题的答案将特定于您正在使用的实现。

+0

我使用gcc,它有一个优化选项列表:http://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc /Optimize-Options.html。但我无法找到似乎适用的一个。关键是'可能'不是真的可以接受的。 – Sjimmie 2012-02-04 12:26:30

+0

@Sjimmie:我的猜测是它不会优化它。你有没有检查编译好的代码? – 2012-02-04 12:34:41

0

V表通常不仅用于虚拟功能,但它也可以用来识别类的类型,当你做一些dynamic_cast或当程序访问type_info为类。

如果编译器检测到没有虚拟函数需要动态分派,并且没有使用其他功能,则它可以将优先级作为优先级移除。

很显然,编译器编写者并没有发现这样做的麻烦。可能是因为它不会经常使用。