2

可能重复:
为什么模板只能在头文件中实现?

我意识到在 SO 上已经很少有这样的话题,但我没有找到任何可以回答我的问题的话题。

我已经使用本教程http://www.codeproject.com/Articles/4750/Singleton-Pattern-A-review-and-analysis-of-existin编写了我的模板单例类

但不幸的是,我不断收到错误:

/home/USER/testcode/cpp_workshop/main.cpp:-1: 错误: 未定义对“Singleton::Instance()”的引用:-1: 错误: collect2: ld

我的单例.h

#ifndef SINGLETON_H
#define SINGLETON_H

template <typename T>
class Singleton
{
public:
    static T& Instance();

protected:
    virtual ~Singleton();
    inline explicit Singleton();

private:
    static T* _instance;
    static T* CreateInstance();
};

template<typename T>
T* Singleton<T>::_instance = 0;

#endif // SINGLETON_H

单例.cpp

#include "singleton.h"
#include <cstdlib>

template <typename T>
Singleton<T>::Singleton()
{
    assert(Singleton::_instance == 0);
    Singleton::_instance = static_cast<T*>(this);
}

template<typename T>
 T& Singleton<T>::Instance()
{
    if (Singleton::_instance == 0)
    {
        Singleton::_instance = CreateInstance();
    }
    return *(Singleton::_instance);
}

template<typename T>
inline T* Singleton<T>::CreateInstance()
{
    return new T();
}

template<typename T>
Singleton<T>::~Singleton()
{
    if(Singleton::_instance != 0)
    {
        delete Singleton::_instance;
    }
    Singleton::_instance = 0;
}

这就是我所说的(使用 normall - 不是模板或任何东西 - 类GameSingleton<Game>::Instance().run();

4

3 回答 3

3

将您的方法定义放在标题中的类定义下,然后删除您的 cpp. 模板化方法和模板化类的方法必须在标头中定义(有几个骇人听闻的例外)。

根据请求,以下是“骇人听闻的例外”:

  • 1) 见@Desmond Hume 的回答
  • 2) 仅使用定义方法的 cpp 中的模板类。例如,您可以在 cpp 的未命名命名空间中声明/定义模板类,这很好。
于 2012-07-12T13:23:57.793 回答
2

您可以将您的Singleton类的定义放入头文件中,或者您可以保持声明(头文件)和定义( .cpp文件)的分离,如果您更喜欢它并Singleton使用每个您将要使用它的类型。要显式实例化Singleton类,请尝试将以下内容放在 .cpp 文件的末尾:

template
class Singleton<Game>;

对于另一种类型,它的外观相同:

template
class Singleton<AnotherGame>; // just for example
于 2012-07-12T13:31:00.237 回答
0

不可能将模板类的定义(头文件)和实现(cpp)分开。所以你有两种解决方案之一:

1-实现头文件.h中的所有内容。像这样的东西

template <typename T>
class Singleton
{
public:
    static T& Instance(){}

protected:
    virtual ~Singleton(){}
    inline explicit Singleton(){}

private:
    static T* _instance;
    static T* CreateInstance(){}
};

另一种解决方案是将 .cpp 类重命名为 .hpp。不要在 .hpp 文件中包含 .h 文件,反之亦然。即在 .h 文件中包含 .hpp 文件

我个人更喜欢第一种解决方案

干杯

于 2012-07-12T13:29:41.843 回答