C ++: неопределенная ссылка на экземпляр в классе Singleton - PullRequest
8 голосов
/ 27 января 2010

Я сейчас пытаюсь реализовать фабрику как синглтон. Я практически использовал учебный пример синглтон-паттерна. Вот файл .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'

На данный момент три ученика поставлены в тупик. Есть идеи?

Ответы [ 5 ]

14 голосов
/ 27 января 2010

Вы должны определить статический экземпляр, а не просто объявить его. Определение создает фактический объект, на который вы ссылаетесь.

В вашем файле cpp добавьте строку:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
2 голосов
/ 27 января 2010

В вашем C ++ добавить это:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
2 голосов
/ 27 января 2010

Вам нужно определение статического члена в файле cpp.

boost::shared_ptr<ImpFactory> ImpFactory::mInstance;
0 голосов
/ 27 января 2010

Поскольку вы используете 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.

0 голосов
/ 27 января 2010

с другой стороны, возможно, вы должны сделать указатель экземпляра статическим членом функции get, а не класса, это не имеет большого значения, если вы используете метод new / pointer. но если вы просто создаете статический экземпляр (т.е. не используете указатель и не возвращаете ссылку на него из функции get get), это имеет большое значение, потому что:

Если он является статическим членом класса, его конструктор вызывается всякий раз, когда (потому что он глобальный), если он является статическим членом функции get, он не создается до тех пор, пока не будет вызван в первый раз, это облегчает некоторые из проблемы, с которыми люди сталкиваются с синглетами и их прославляют глобалы, другая хорошая вещь: большинство компоновщиков пропускают функцию get и, следовательно, статический экземпляр полностью, если он никогда не вызывается, поэтому вам не нужно беспокоиться о вызове new, чтобы он использует только память, если она используется.

...