8

我目前正在尝试将工厂实现为单例。我实际上使用了单例模式的教科书示例。这是.h文件:

namespace oxygen{

class ImpFactory{

public:
    static boost::shared_ptr<ImpFactory> GetInstance();

private:
    static boost::shared_ptr<ImpFactory> mInstance;
};

这是 .cpp 文件:

#include "impfactory.h"

using namespace oxygen;
using namespace boost;

shared_ptr<ImpFactory> ImpFactory::GetInstance(){
    if (mInstance.get() == 0)
        mInstance = shared_ptr<ImpFactory>(new ImpFactory());
    return mInstance;
}

代码编译,但我得到一个链接器错误:

../../lib/oxygen/liboxygen.so.3.2.4:未定义对“oxygen::ImpFactory::mInstance”的引用

目前这让三名学生难倒。有任何想法吗?

4

5 回答 5

14

您必须定义静态实例,而不仅仅是声明它。该定义创建您引用的实际对象。

在您的cpp文件中,添加以下行:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
于 2010-01-27T08:19:01.257 回答
2

您需要在 cpp 文件中定义静态成员。

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
于 2010-01-27T08:19:37.417 回答
2

在你的 c++ 中添加这个:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
于 2010-01-27T08:19:40.413 回答
0

另一方面,也许您应该使实例指针成为 get 函数而不是类的静态成员,这在使用 new/pointer 方法时并没有太大的区别。但是,如果您只是创建一个静态实例(即不使用指针,并从 get get 函数返回对它的引用),这会产生很大的不同,因为:

如果它是一个类的静态成员,它的构造函数在任何时候都会被调用(因为它是一个全局的)如果它是 get 函数的静态成员,它直到它第一次被调用时才被构造,这减轻了人们遇到的一些问题使用单例并且它们被美化为全局变量,另一个好处是,大多数链接器将省略 get 函数,因此如果它从未被调用,则完全省略静态实例,因此您不必担心调用 new 以便它只使用内存如果它正在被使用。

于 2010-01-27T09:04:54.420 回答
0

由于您使用的是 Boost,因此您可能需要考虑 Boost 单例类。查看:

#include <boost/serialization/singleton.hpp>

using namespace boost::serialisation;

struct MyClass : public singleton<MyClass>
{ string name_; int age_; };

int main( int argc, char* argv[] )
{
    MyClass::get_mutable_instance().name_ = "Robin";
    MyClass::get_mutable_instance().age_ = 21;
}

你使用哪个取决于你在做什么。虽然出于通常的原因我有点反对单例,但在可能的情况下重复使用是有意义的。不过要提醒一句:Boost 单例似乎在库中移动了一点,因此这可能会根据您使用的 Boost 版本而有所不同。

于 2010-01-27T10:20:35.273 回答