2015-01-23 2 views
0

Я пытаюсь реализовать шаблон проектирования singleton без выделения памяти. Я попытался найти решение, но похоже, что каждое решение предназначено для одного сингла, определенного с распределением памяти.C++ Singleton: `Undefined reference to` error

Я сделал конструктор приватным и единственный код, который я добавил в файл заголовка, чтобы сделать это синглтон шаблон дизайна был:

static ParametersServerPC& ParametersServerPC::GetInstance() { 

    static ParametersServerPC instance; 
    return instance; 

} 

Это производный класс от базового класса ParametersServerABS который имеет пустой конструктор определение. ParametersServerABS - абстрактный класс.

Когда я пытаюсь создать экземпляр ParametersServerPC класс в отдельном файле:

ParametersServerPC& paramServer = ParametersServerPC::GetInstance(); 

Я получаю эту ошибку:

undefined reference to `ParametersServerPC::GetInstance()' 

здесь являются .cpp и .hpp файлы:

parameters_server_abs. hpp:

#ifndef PARAMETERS_SERVER_ABS_HPP_ 
#define PARAMETERS_SERVER_ABS_HPP_ 

class ParametersServerABS { 

    public: 

     ParametersServerABS(); 

     ~ParametersServerABS(); 

     virtual bool Load() = 0; 

}; 

#endif 

parameters_server_abs.cpp:

#include "mid_level/parameters_server_abs.hpp" 

ParametersServerABS::ParametersServerABS() {} 

ParametersServerABS::~ParametersServerABS() {} 

parameters_server_pc.hpp:

#ifndef PARAMETERS_SERVER_PC_HPP_ 
#define PARAMETERS_SERVER_PC_HPP_ 

#include <string> 

#include "mid_level/parameters_server_abs.hpp" 

class ParametersServerPC: public ParametersServerABS { 

    public: 

     ~ParametersServerPC(); 

     static ParametersServerPC& GetInstance(); 

     virtual bool Load(); 

    private: 

     ParametersServerPC(std::string parameterFileName = "parameters.txt"); 

     std::string _parameterFileName; 

}; 

parameters_server_pc.cpp:

#include "mid_level/parameters_server_pc.hpp" 

ParametersServerPC::ParametersServerPC(std::string parameterFileName = "parameters.txt") : 
     _parameterFileName(parameterFileName) { 

} 

ParametersServerPC::~ParametersServerPC() { 

} 

static ParametersServerPC& ParametersServerPC::GetInstance() { 

    static ParametersServerPC instance; 
    return instance; 

} 

virtual bool ParametersServerPC::Load() { 

    return true; // TODO 

} 

my_test_file.cpp

#include "mid_level/parameters_server_pc.hpp" 

ParametersServerPC& paramServer = ParametersServerPC::GetInstance(); 
+0

Не могли бы вы разместить весь код 'ParametersServerPC'? 'GetInstance()' отлично выглядит, но в определении не требуется 'static'. –

+0

'ParametersServerABS' - абстрактный класс, из которого получен класс' PC'. Сейчас у него есть публичный конструктор и деструктор. Наряду с виртуальной функцией, которую я еще не определил. Код для GetInstance() в классе 'PC' находится в файле заголовка. Сейчас все, что у него есть, - это публичный деструктор и частный конструктор. –

+0

@VictorPolevoy Конечно, 1 сек. –

ответ

1

undefined reference to `ParametersServerPC::GetInstance()'

Это, кажется, ошибка компоновщика. Если вы можете опубликовать вывод консоли компиляции, мы можем сузить его дальше.

Тем временем вы можете проверить свою систему сборки и посмотреть, не опущены ли некоторые исходные файлы из компиляции.

На одноэлементном образце уже есть некоторые хорошие ответы. Подробнее по теме in a description of the pattern и in a general question about singletons.

+0

Да, мне нужно было отредактировать мой файл CMake, чтобы включить файлы .cpp. Благодаря! –

1

Это приемлемый шаблон. Вот MVCE демонстрации осуществимости:

#include <iostream> 
#include <string> 

using namespace std; 

class A { 
public: 
    int ival; 
    string strval; 

    static A& getInstance(); 
private: 
    A(int ival, string strval): ival(ival), strval(strval) {} 
    A(A& src): ival(src.ival), strval(src.strval) {} 
    ~A() {}; 
}; 

A& A::getInstance() { 
    static A instance(1, "foo"); 

    return instance; 
} 



int main() { 
    A& a = A::getInstance(); 
    cout << a.ival << endl; 

    // A a1 = A::getInstance(); error 
    // A a2 = a; error 
    // A a3(2, "bar"); error 

    return 0; 
} 
+0

Должен ли деструктор быть закрытым? Возможно, это моя проблема. –

+0

@JustinLiang Поскольку конструкторы являются частными, вы не можете создать другой экземпляр вне класса. Я написал деструктор private только для того, чтобы разрешить любую попытку сделать A * pa = A :: getInstance(); delete pa; 'обнаружен как ошибка во время компиляции. Во всяком случае, это будет ошибка времени выполнения, поскольку «экземпляр» не был назначен «новым». –

1

Во-первых, отметьте ваш ~ParametersServerABS(); деструктор virtual, чтобы иметь возможность удалить объекты должным образом. Во-вторых, вам нужно удалить virtual и static ключевые слова из parameters_server_pc.cpp файл: они предназначены только для определений (для вашего файла заголовка).

Далее, сделать это правильно:

class ParametersServerPC { 
    // your code 

    private: 
     ParametersServerPC(std::string parameterFileName = "parameters.txt"); 
     ParametersServerPC(ParametersServerPC const&) = delete; 
     void operator=(ParametersServerPC const&) = delete; 
}; 

Singleton означает, что вы не можете получить копии объекта: необходимо запретить использование конструктора копирования и копирующий оператор присваивания. И в любом случае я думаю, что ваша проблема в static в вашем parameters_server_pc.cpp файла. Удалите его из части реализации (файл cpp), чтобы исправить проблему, но ОСТАВИТЕ ее в части определения (заголовочный файл).

+0

Первый вопрос: мне не нужно удалять ключевое слово 'static' из файла' parameters_server_pc.hpp'? –

+0

Нет, вам нужно оставить его там, но удалить его из 'parameters_server_pc.cpp'. –

+0

Спасибо за помощь! Хотя я все еще получаю ошибку после внесения всех изменений, которые вы мне рассказывали. За исключением того, что я не удалял ключевое слово 'static' внутри моей функции' GetInstance() 'в файле' parameters_server_pc.cpp' –