2011-08-11 3 views
3

私はテンプレート化された関数を持つ基本クラスを持っています。テンプレート化された関数は一般的なテンプレート化された型を持ちます。テンプレートクラス(特殊)を子クラスにオーバーロードするにはどうすればよいですか?

#ifndef BASE_CLASS 
#define BASE_CLASS 

#include <iostream> 

using namespace std; 

struct Type1 
{ 
}; 

struct Type2 
{ 
}; 

class baseClass 
{ 
    public: 
    template<class Type> 
    void doStuff(Type & t) 
     { 
     templateFunction(t); 
     } 

    template<class Type> 
    void templateFunction(Type & t); 
}; 

template<class Type> 
void baseClass::templateFunction(Type & t) 
{ 
    cout << "This is the generic function!" << endl; 
} 

template<> 
void baseClass::templateFunction(Type1 & t) 
{ 
    cout << "This is the specialized function: - Type1" << endl; 
} 
#endif 

また、「baseClass」を継承する子クラスもあります。ただし、子クラスはその特殊化のために異なる機能を必要とします。

#ifndef CHILD_CLASS 
#define CHILD_CLASS 

#include "BaseClass.h" 

class ChildClass : public baseClass 
{ 
    public: 

}; 

template<> 
void ChildClass::templateFunction(Type1 & t) 
{ 
    cout << "We overloaded the specialized template function for type 1!" << endl; 
} 

#endif 

上記コンパイルされない:

ChildClass.h:13:エラー:âtemplateFunctionâがâChildClassâ ChildClass.hで宣言されないメンバ関数:13:エラー:無効な関数宣言

場合私"オーバーロードされた" 機能を変更します。

template<> 
void baseClass::templateFunction(Type1 & t) 
{ 
    cout << "We overloaded the specialized template function for type 1!" << endl; 
} 

私が手: ChildClass.h:13:エラー:避けるBAの再定義をseClass :: BaseClass.h A [タイプ=タイプ1付き] templateFunction(タイプ&):36:エラー:避ける基底クラス:: [タイプと=のType1] templateFunction(タイプ&)以前ここ

するにはどうすればよいです宣言â私は正しく、子クラスの特殊なテンプレート関数をオーバーロードしますか?参考のため

、メイン:の提案に

#include "BaseClass.h" 
#include "ChildClass.h" 

int main() 
{ 
    Type1 first; 
    Type2 second; 

    baseClass theBaseClass; 
    ChildClass theChildClass; 


    theBaseClass.doStuff(first); 
    theBaseClass.doStuff(second); 

    theChildClass.doStuff(first); 
    theChildClass.doStuff(second); 

    return 0; 
} 

#ifndef CHILD_CLASS 
#define CHILD_CLASS 

#include "BaseClass.h" 
class ChildClass : public baseClass 
{ 
    public: 
    template<class Type> 
    void templateFunction(Type & t); 
}; 

template<> 
void ChildClass::templateFunction(Type1 & t) 
{ 
    cout << "We overloaded the specialized template function for type 1!" << endl; 
} 

#endif 

出力:

This is the specialized function: - Type1 
This is the generic function! 
This is the specialized function: - Type1 
This is the generic function! 
Kerrek SBは、私はにChildClassを変更しました

私は望んでいた:

This is the specialized function: - Type1 
This is the generic function! 
We overloaded the specialized template function for type 1! 
This is the generic function! 

これはまだ動作しません。

+1

テンプレート化機能を仮想することはできません、あなたが派生クラスのメンバ関数を再定義する意味がわかられる一方*隠れ*元の機能?ベースへのポインタを介して再定義された関数に到達することはできません!確かな場合は、非特化宣言を派生クラスに追加する必要があります。 –

+0

私はbaseClassのオリジナルの特別な機能にアクセスする必要はありません。少なくともChildClassの任意のインスタンスに対して。 – Alex

+1

その場合は、関数のプライマリテンプレート宣言を特殊化する前に派生クラスに追加すると、それを実行できるはずです。 –

答えて

5

あなたが望むように機能しない理由は、その機能が親クラスでは仮想ではないということです。ただし、仮想テンプレート機能を使用することはできません。rhalbersmaが提案されているよう

  • 、自身がテンプレートクラスを作成し、その後、子クラスで必要なメソッドの(今されていないテンプレート)をオーバーライドします。

    は、私は2つの主要なオプションを参照してください。
  • 特殊なメソッドの場合は、必要な処理を行うだけで、新しいメソッドを別の名前で作成してください。

しかし、私は、誰かが良いアイデアを思い付くだろうと確信している... =)

2

このような仮想関数でテンプレートクラスを作ることができる:テンプレートT、またはダイナミック型(D対B)のいずれか:

template<typename T> 
class B 
{ 
    virtual void f() { std::cout << "base template implementation \n"; } 
}; 

template<> 
class B<Type1> 
{ 
    virtual void f() { std::cout << "base specialized implementation \n"; } 
}; 

template<typename T> 
class D: public B<T> 
{ 
    virtual void f() { std::cout << "derived template implementation \n"; } 
}; 

template<> 
class D<Type1>: public B<Type1> 
{ 
    virtual void f() { std::cout << "derived specialized implementation \n"; } 
}; 

B<Type1> b1; 
B<Type2> b2; 
D<Type1> d1; 
D<Type2> d2; 

b1.f(); 
b2.f(); 
d1.f(); 
d2.f(); 

次にカスタマイズ2つの独立した大きさがあります。各テンプレートインスタンス化では、仮想関数を再定義することができます。

より一般的なのは、純粋な仮想関数(つまりインターフェイス)を持つ通常のクラスであり、DをBから派生するテンプレートクラスとすることです。これにより、Bの仮想関数をそれぞれ異なる方法で再定義できますDのテンプレートインスタンス化(適切なデフォルトを持つ)。

関連する問題