3

テンプレート化された基本クラスを使用し、それを継承して Service Locator パターンを実装しようとしています。

    // Header File
    namespace one {
    template <class I, class N>
    class Locator {
    public:
        static void initialize() {
            service = &nullService;
        }
        static void provide(I* newService) {
            if (newService == 0) {
                initialize();
            } else {
                service = newService;

        }
        static I& get() { return *service; }
        virtual ~Locator() {
            if (service != &nullService) {
                delete service;
            }
    private:
        Locator();
        static I* service;
        static N nullService;
    };
    }

    // Source File
    #include "Locator.hpp"

    namespace one {
    template<class I, class N>
    I* Locator<I, N>::service;

    template<class I, class N>
    N Locator<I, N>::nullService;
    }

クラス Iはインスタンス クラスで、クラス Nはヌル サービス クラスです。派生クラスの場合:

    // Header File
    namespace two {
    class ExampleLocator : public one::Locator<Service, NullService> {}
    }

    // Source File
    namespace one {
    template class Locator<Service, NullService>;
    }

この実装を試してみると、

    int main(int argc, char const *argv[]) {
        two::ExampleLocator::initialize();
        two::ExampleLocator::get().doSomething();
    }

gcc は次のエラーでコンパイルに失敗します:

  • one::Locator::initialize() への未定義の参照
  • 関数 one::Locator::get() 内: one::Locator::service への未定義の参照

私は何を間違っていますか?

注: 派生クラスの cpp で Locator の静的プロパティを再宣言することで、プロジェクトをコンパイルできます。

    // Alternative Derived class Source file
    namespace one {
    template<class I, class N>
    I* Locator<I, N>::service;

    template<class I, class N>
    N Locator<I, N>::nullService;

    template class Locator<Service, NullService>;
    }

注 2: Derived クラスは、Locator クラスとは異なる名前空間にあります。

4

1 に答える 1

5

テンプレート定義は、それらを使用するすべての翻訳単位で表示される必要があります。.cpp ファイル内のコードを .hpp ファイルに移動します。

参照:テンプレートをヘッダー ファイルにしか実装できないのはなぜですか?

于 2012-12-19T12:19:38.953 に答える