当对象具有值语义时,在方法中内联虚函数

时间:2014-12-18 05:10:53

标签: c++ inline compiler-optimization virtual-functions template-method-pattern

使用模板方法设计模式考虑以下代码:

class A {
    public:
        void templateMethod() {
            doSomething();
        }
    private:
        virtual void doSomething() {
            std::cout << “42\n”;
        }
};
class B : public A {
    private:
        void doSomething() override {
            std::cout << “43\n”;
        }
};

int main() {
    // case 1
    A a; // value semantics
    a.templateMethod(); // knows at compile time that A::doSomething() must be called

    // case 2
    B b; // value semantics
    b.templateMethod(); // knows at compile time that B::doSomething() must be called

    // case 3
    A& a_or_b_ref = runtime_condition() ? a : b;  // ref semantics 
    a_or_b_ref.templateMethod(); // does not know which doSomething() at compile time, a virtual call is needed
    return 0;
}

我想知道编译器是否能够在案例1和2中内联/取消虚拟化“doSomething()”成员函数。 如果它为templateMethod()创建3个不同的二进制代码片段,则可以实现:一个没有内联,一个没有内联的A :: doSomething()或者B :: doSomething()(在情况3中必须分别调用, 1和2)

您知道标准是否需要此优化,或者是否有任何编译器实现它? 我知道我可以用CRT模式实现同样的效果而不是虚拟,但意图不太明确。

2 个答案:

答案 0 :(得分:1)

该标准一般不需要优化(偶尔会不允许它们);它指定了结果,由编译器决定如何最好地实现它。

在所有三种情况下,我都希望内联templateMethod。然后编译器可以自由地执行进一步的优化;在前两种情况下,它知道this的动态类型,因此可以为doSomething生成非虚拟调用。 (然后我希望它可以内联这些电话。)

查看生成的代码并亲自查看。

答案 1 :(得分:0)

优化是编译器不是标准的问题。如果优化导致不尊重或虚函数的原理,那将是一个主要的错误。

所以在第三种情况下:

// case 3
A& b_ref = b; // ref semantics   
b_ref.templateMethod();

实际对象是B,并且调用的实际函数必须是B类中定义的函数,无论指针的引用是什么。

我的编译器正确显示43 - 它显示了我会立即改变编译器的其他内容......