2016-12-15 9 views
4

次のコードを検討してください。 Derived<int>::foo()がインスタンス化されることが保証されていますか? foo()は仮想であり、基本クラスの非仮想関数によって呼び出されます。テンプレートクラスの仮想関数が暗黙的にインスタンス化されていますか?

#include <iostream> 

class Base 
{ 
public: 
    void bar() { foo(); } 
private: 
    virtual void foo() = 0; 
}; 

template <typename T> class Derived: public Base 
{ 
public: 
    Derived(T t_) : t(t_) {} 
private: 
    void foo() override { std::cout << t; } 
    T t; 
}; 

Derived<int> make_obj() 
{ 
    return Derived<int>(7); 
} 
+0

ここで私の足を考える。テンプレートインスタンス化エンジンは、どの仮想関数が使用され、どの仮想関数が使用されていないのかを知る方法がありません。安全であるためには、すべての 'virtual'関数をインスタンス化する必要があります。 –

答えて

5

標準セクション14.7.1/11は、仮想メンバ関数が他のインスタンス化されない場合、実装は、暗黙的にクラステンプレートの仮想メンバー関数をインスタンス化するか否かを指定されていない

言います。

しかし、典型的なvtableの実装では、クラスの任意のコンストラクタをインスタンス化するには、クラスが存在するvtableが必要です。これには、特殊化の仮想関数定義へのポインタが含まれている必要があります。実際には、仮想関数はおそらくインスタンス化されます。

+2

私は、この定式化が、vtableを最適化できるならば、それ以外の場合は未使用の仮想関数をすべてインスタンス化する必要はないという実装に十分な余裕があると思います。問題の例では、このような最適化の機会が与えられます。多型が関与していません。 – j6t

0

バーチャルテーブルは常にクラス階層のためにインスタンス化されますが、クラス自体がスタック上で初期化され、多相的に使用されていないため、fooが実際にクラス作成時に初期化されるかどうかはコンパイラによって異なります。あなたの場合、仮想テーブルは無意味です。

関連する問題