2012-04-18 16 views
10

O.Kですか?その本体の外側にあるクラステンプレートの仮想関数を定義するには?仮想関数をインライン化することはできませんが、コンパイル単位で複数の定義を避けるために、inlineとマークされます(テンプレートヘッダは複数のソースファイルに含まれるものとします)。一方、コンパイラはinlineを無視しても問題ありません。たとえば、以下のコードは正しいですか?クラス定義外のテンプレート定義

template <typename T> 
class C 
{ 
public: 
    virtual void f(T val); 
}; 

template <typename T> 
inline 
void C<T>::f(T val) 
{ 
    //definition 
} 

BTW gcc(3.4.2)は、関数f(T val)の定義の前にinlineを省略することができますが、通常のクラスの類似機能の前には使用できません。 gccの動作だけですか?

+5

gcc * 3.4.2 *を使用していますか? – jpalecek

+0

@jpalecekこの特定の例では、はいです。 – doc

+1

@doc - 仮想関数*は 'inline'宣言できます(ただし、ここでは必要ありません)。コンパイラは、関数がいつインライン化できるかを正確に把握するのが少し難しくなっています。 –

答えて

10

はい、それもinlineなくてOKですそれは普通のメンバ関数のために同じことを動作し、静的変数:

// everything in the header: 
template <class T> 
class A 
{ 
    static int i; 
}; 

template <class T> 
int A<T>::i=0; 

標準引用:(3.2/5)

が存在することができMOR列タイプ(7.2)、 外部リンケージ(7.1.2)、クラステンプレート(14章)、非静的関数テンプレート(14.5.6)、静的関数テンプレートデータテンプレート クラステンプレート(14.5.1.3)、クラステンプレートのメンバ関数(14.5.1.1)、または のテンプレート特殊化(いくつかのテンプレートパラメータが提供されているプログラムでは指定されていない(14.7,14.5.5))各デFi回線nition はディFF erentの翻訳単位で表示され、提供したデFiをnitionsは

要件は基本的に2つの定義が同じになるように持っていると言う...次の要件を満たします。

通常のクラスの場合は動作しません。プログラム全体で最大で1つの定義が必要です。

+0

なぜ誰かがこの回答をダウン投票しました:? – doc

3

問題の関数をインスタンス化する必要があるコードがコンパイル時(リンク時ではなく)にそのコードの可視性を持っている限り、そこで関数を定義できます。

テンプレートを2つのファイルに分けるのはよくあることです.1つは従来のヘッダーで、もう1つは実装で、テンプレート化されていない関数やその実装と同じです。唯一の違いは、テンプレート実装ファイルとヘッダーを#includeする必要があることです。

4

classの定義外のテンプレートメソッドを同じヘッダーに定義することができます。inlineを使用せずに、複数の定義エラーを受け取ることなく使用できます。

完全に特殊化されていないテンプレート・ファンクションは、定義自体を生成しないためです。。私のポイントを証明するために、次の関数は、この場合の定義を持っているよう

void C<int>::f(int) 
{ 
} 

は、リンカエラーになります。 (あなたが複数の翻訳単位でこれを含まれていないあなたは、インラインそれをマークした場合は提供:。。。

inline void C<int>::f(int) 
{ 
} 

エラーが発生しなくなった