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 つの異なるバイナリ コードを作成する場合に可能です: A::doSomething() または B::doSomething() のいずれかをインライン化 (ケース 3、1、および 2 でそれぞれ呼び出す必要があります)

この最適化が標準で必要かどうか、またはコンパイラがそれを実装しているかどうかを知っていますか? CRT パターンを使用し、仮想パターンを使用せずに同じ種類の効果を達成できることはわかっていますが、意図はあまり明確ではありません。

4

2 に答える 2

1

標準では、一般に最適化は必要ありません (場合によっては、無理に許可することもあります)。結果を指定し、それを達成するための最善の方法を見つけるのはコンパイラ次第です。

templateMethod3つのケースすべてで、インライン化されると予想されます。その後、コンパイラは自由にさらなる最適化を実行できます。最初の 2 つのケースでは、 の動的な型を認識しているthisため、 の非仮想呼び出しを生成できますdoSomething。(私はそれがそれらの呼び出しをインライン化することを期待しています。)

生成されたコードを見て、自分の目で確かめてください。

于 2014-12-18T09:25:27.413 に答える
0

最適化は、標準ではなくコンパイラの問題です。最適化が非尊重または仮想関数の原則につながる場合、これは重大なバグになります。

したがって、3番目のケースでは:

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

実際のオブジェクトは B であり、呼び出される実際の関数は、使用されるポインターの参照が何であれ、B クラスで定義されたものでなければなりません。

そして、私のコンパイラは正しく表示されます43-すぐにコンパイラを変更したであろう何かが表示されましたか...

于 2014-12-18T10:36:17.890 に答える