C++ 单例:`未定义的引用` 错误
C++ Singleton: `Undefined reference to` error
我正在尝试实现一个没有内存分配的单例设计模式。我尝试寻找解决方案,但似乎每个解决方案都是针对使用内存分配定义的单例。
我将构造函数设为私有,我添加到头文件以使其成为单例设计模式的唯一代码是:
static ParametersServerPC& ParametersServerPC::GetInstance() {
static ParametersServerPC instance;
return instance;
}
这是从具有空构造函数定义的基 class ParametersServerABS
派生的 class。 ParametersServerABS
是一个摘要 class.
当我尝试在单独的文件中实例化 ParametersServerPC
class 时:
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();
这是一个可以接受的模式。这是一个展示可行性的 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;
}
首先,标记您的 ~ParametersServerABS();
析构函数 virtual
以便能够正确删除对象。其次,您需要从 parameters_server_pc.cpp 文件中删除 virtual
和 static
关键字:它们仅用于定义(对于您的头文件)。
接下来,做对了:
class ParametersServerPC {
// your code
private:
ParametersServerPC(std::string parameterFileName = "parameters.txt");
ParametersServerPC(ParametersServerPC const&) = delete;
void operator=(ParametersServerPC const&) = delete;
};
单例意味着你无法获取对象的副本:你需要禁止使用复制构造函数和复制赋值运算符。
无论如何,我认为您的问题出在 parameters_server_pc.cpp 文件中的 static
中。从实现部分(cpp 文件)中删除它以解决问题,但将其保留在定义部分(头文件)中。
undefined reference to `ParametersServerPC::GetInstance()'
这似乎是链接器错误。如果您可以 post 编译控制台的输出,我们可能会进一步缩小范围。
在此期间,您可以检查您的构建系统,看看您是否在编译时遗漏了一些源文件。
关于单例模式已经有一些很好的答案。有关该主题的更多信息 in a description of the pattern and in a general question about singletons。
我正在尝试实现一个没有内存分配的单例设计模式。我尝试寻找解决方案,但似乎每个解决方案都是针对使用内存分配定义的单例。
我将构造函数设为私有,我添加到头文件以使其成为单例设计模式的唯一代码是:
static ParametersServerPC& ParametersServerPC::GetInstance() {
static ParametersServerPC instance;
return instance;
}
这是从具有空构造函数定义的基 class ParametersServerABS
派生的 class。 ParametersServerABS
是一个摘要 class.
当我尝试在单独的文件中实例化 ParametersServerPC
class 时:
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();
这是一个可以接受的模式。这是一个展示可行性的 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;
}
首先,标记您的 ~ParametersServerABS();
析构函数 virtual
以便能够正确删除对象。其次,您需要从 parameters_server_pc.cpp 文件中删除 virtual
和 static
关键字:它们仅用于定义(对于您的头文件)。
接下来,做对了:
class ParametersServerPC {
// your code
private:
ParametersServerPC(std::string parameterFileName = "parameters.txt");
ParametersServerPC(ParametersServerPC const&) = delete;
void operator=(ParametersServerPC const&) = delete;
};
单例意味着你无法获取对象的副本:你需要禁止使用复制构造函数和复制赋值运算符。
无论如何,我认为您的问题出在 parameters_server_pc.cpp 文件中的 static
中。从实现部分(cpp 文件)中删除它以解决问题,但将其保留在定义部分(头文件)中。
undefined reference to `ParametersServerPC::GetInstance()'
这似乎是链接器错误。如果您可以 post 编译控制台的输出,我们可能会进一步缩小范围。
在此期间,您可以检查您的构建系统,看看您是否在编译时遗漏了一些源文件。
关于单例模式已经有一些很好的答案。有关该主题的更多信息 in a description of the pattern and in a general question about singletons。