6

考虑以下带有模板方法设计模式的代码:

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 段不同的二进制代码,这是可能的:一个没有内联,2内联 A::doSomething() 或 B::doSomething() (在情况 3、1 和 2 中必须分别调用)

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

4

2 回答 2

1

该标准通常不需要优化(有时它会不遗余力地允许它们);它指定了结果,由编译器决定如何最好地实现它。

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

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

于 2014-12-18T09:25:27.413 回答
0

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

所以在第三种情况下:

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

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

而且我的编译器显示正确43- 它是否显示了我会立即更改编译器的任何其他内容......

于 2014-12-18T10:36:17.890 回答