0

単一の引数を取るコンストラクターを持つテンプレート化されたクラスがあります。2番目のテンプレート型の引数を取る関数への関数ポインタ。そして、最初のテンプレートタイプの要素を返します。

コードは次のとおりです。

cache_controller.hpp:

template<class TYPE, class KEY>
class cache
{
    private:
        TYPE (*create_func)(KEY);
    public:
        cache(TYPE (*func)(KEY));
};

extern sf::Texture * create_texture(std::string path);

cache_controller.cpp:

template<class TYPE, class KEY>
cache<TYPE, KEY>::cache(TYPE (*func)(KEY))
{
    this->create_func = func;
}

sf::Texture * create_texture(std::string path)
{
    sf::Texture * tex_p = new sf::Texture;
    tex_p->loadFromFile(path);
    return tex_p;
}

テストコード:

cache<sf::Texture *, std::string> tcache(&create_texture);

ただし、リンクすると次のエラーが発生します。

[Linker error] main.cpp:11: undefined reference to `cache<sf::Texture*, std::string>::cache(sf::Texture* (*)(std::string))' 

もちろん、任意のキー、値、および作成関数を使用してオブジェクトキャッシュを実装する簡単な方法があれば、私はすべて耳を傾けています。

4

2 に答える 2

3

テンプレートクラスのメンバー関数の定義を.cppファイルで提供します。

これらのメンバー関数の定義は、インスタンス化ポイントでコンパイラーに表示される必要があります(つまり、.cppこれらの関数を呼び出すファイルから)。そうでない場合、宣言のみが表示され、コンパイラーは他の場所で定義されている関数に依存します。別の変換単位を処理している間。

その定義がコンパイラに表示される変換ユニット(つまり.cppファイル)にはその関数のインスタンス化がないため、何も生成されず、リンカは最終的に定義が提供されていないと文句を言います。

のコンストラクターの定義はcache、クラステンプレートcacheが定義されているヘッダーファイル(この場合はcache_controller.hpp)に配置する必要があります。

于 2013-02-09T14:00:36.270 に答える
2

テンプレート化されたメソッドの実装は、その宣言を保持するファイルと一致する必要があります。テンプレートのインスタンス化はコンパイル時の操作であり、リンク時ではありません。リンカエラーを解決するには、2つを互いにマージします。つまり、クラス内またはクラス外の同じファイル内にコンストラクターを実装します。

于 2013-02-09T14:00:22.443 に答える