子类可以内联一个非基类内联的纯虚方法吗?

时间:2011-09-29 17:43:02

标签: c++ virtual

据我了解,编译器可以在编译时知道对象的类型在运行时(C++ faq)时内联虚函数调用。

但是,当从基类实现纯虚方法时会发生什么?是否适用相同的规则?是否会内联以下函数调用?

class base
{
public:
    virtual void print() = 0;

    virtual void callPrint()
    {
        print(); // will this be inline?
    }
};

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

int main()
{
    child c;
    c.callPrint();

    return 0;
}

修改

我认为我原来的示例代码实际上是我想要问的不好的代表。我已经更新了代码,但问题仍然存在。

3 个答案:

答案 0 :(得分:10)

编译器永远不需要 来内联函数调用。在这种情况下,允许内联函数调用,因为它知道c的具体类型(因为它不通过指针或引用间接,编译器可以看到它在哪里被分配为child)。因此,编译器知道使用了print()的哪个实现,并且可以选择不执行vtable间接,并进一步选择内联函数的实现。

但是,编译器也可以内联它;它可能会直接调用child::print(),或者通过vtable直接调用,如果它决定这样做的话。

这些优化通常可归结为“as-if”规则 - 编译器必须按 as 进行完全vtable间接操作 - 这意味着结果必须相同,但如果结果相同,编译器可以选择不同的方法来实现结果。这包括内联等。

答案 1 :(得分:3)

答案当然是&#34;它取决于&#34;,但原则上没有阻碍优化。事实上,你在这里甚至没有做任何多态的事情,所以这真的是直截了当的。

如果你有这样的代码,问题会更有趣:

child c;
base & b = c;
b.print();

关键是编译器在这一点上知道动态调度的最终目标是什么(namly child::print()),因此这有资格进行优化。 (当然,有两个独立的优化机会:一个是通过避免动态调度,一个来自目标的功能体在TU中可见。)

答案 2 :(得分:1)

您应该注意几条规则:

1)编译器永远不会被强制内联 - 甚至使用指令或在头文件中定义方法。

2)多态性必须始终有效。这意味着编译器更愿意通过vftable调用函数,而不是在存在动态调用的可能性时内联函数。