未定义对受保护静态成员的引用。我该如何解决?
undefined reference to protected static member. How do I solve it?
在robots.hpp我有一个class
,robots
。我希望每个机器人都有一个指向另一个机器人的指针,即最后声明的那个。我还希望每个人都有一个唯一的 ID。为此,我有一个变量来计算机器人的数量。
看来我无法在 class 定义中初始化我的静态变量。我查找了如何解决该问题,并在 robots.cpp 中找到了一些建议初始化它们的内容。但是,这给了我一个错误,说它们受到保护,所以我不能那样做。所以现在我有一个函数,它在开始时只被构造函数调用一次。
但是,这给了我一个错误,说我不能这样做,因为它们还没有被定义。
robots.hpp中的class定义:
class robot
{
public:
///initialiser.
robot();
[...]
///initialises all robots
void initrobots();
///id of robot
const uint_least8_t id=NumOfRobots++;
static bool hasBeenInitialised;
protected:
///number of robots.
static uint_least8_t NumOfRobots;
///pointer to the next robot that needs pointing to.
static robot* poiRobot;
[...]
///pointer to next robot
robot* nextRobot;
};
robots.cpp:
bool robot::hasBeenInitialised=false;
void robot::initrobots(){
poiRobot=NULL;
NumOfRobots=0;
}
robot::robot(){
if(!hasBeenInitialised){
initrobots();
hasBeenInitialised=true;
}
[...]
}
产生这个错误的代码是这样的:
#include <cstdint>
#include <cstdlib>
class robot
{
public:
///initialiser.
robot();
//[...]
///initialises all robots
void initrobots();
///id of robot
const uint_least8_t id=NumOfRobots++;
static bool hasBeenInitialised;
protected:
///number of robots.
static uint_least8_t NumOfRobots;
///pointer to the next robot that needs pointing to.
static robot* poiRobot;
//[...]
///pointer to next robot
robot* nextRobot;
};
bool robot::hasBeenInitialised=false;
void robot::initrobots(){
poiRobot=NULL;
NumOfRobots=0;
}
robot::robot(){
if(!hasBeenInitialised){
initrobots();
hasBeenInitialised=true;
}
}
int main(){
return 0;
}
如果我编译它,它不会抱怨,但如果我构建它,它就会抱怨(使用 geany 单独做这些事情,c++11 标准(否则 cstdint 抱怨))
我希望代码使 poiRobot
成为指向 null
的指针,并且 NumofRobots
等于 0。
您应该能够摆脱 static bool hasBeenInitialised;
和 bool robot::hasBeenInitialised=false;
以及您的初始化函数,只需直接在您的 cpp 文件中声明 uint_least8_t robot::NumOfRobots = 0;
和 robot* robot::poiRobot = nullptr
。这样他们就会自动将自己初始化为 0 和 null。如评论中所述,这是有效的,受保护的静态变量应该能够以这种方式在源文件中定义。
编辑:关于您在编辑中 post 编辑的代码,您似乎从未定义 robot::poiRobot 和 robot::NumRobots。你试过我在上面 post 编写的代码了吗?
基本上,你项目中的每一个cpp文件都要被编译器编译成一个翻译单元。然后 linker 通过并将所有翻译单元和 links 放在一起。任何看到你的机器人 class 的 cpp 文件都会看到你已经承诺这两个变量存在于某处,因此当你使用它们时它会允许它(就目前而言,它们存在并且有利于走)。当 linker 出现时,它会看到对这些变量的引用,并尝试找到它们在哪个翻译单元中定义,以便它可以完成它的工作(link 一切都在一起)。此时,它不会在任何翻译单元中看到定义,这就是它给您该错误的原因。
uint_least8_t robot::NumOfRobots = 0;
和 robot* robot::poiRobot = nullptr
是您要查找的定义,应该放在您的 cpp 文件中。如果在使用这些之后你得到另一个关于它们被保护的错误,就像你之前暗示的那样,post 那个代码,这样我们就可以看到为什么会发生这种情况。
关于 "It seems that I can't initialise my static variables in the class definition." 的编辑 2:当您将该定义放入头文件中时,包含您的头文件的每个 cpp 文件都将定义它自己的该变量版本。当 linker 转到 link everything 时,它将在不同的翻译单元中看到同一变量的多个定义,这违反了 C++ (ODR) 中的 "One Definition Rule"。这就是为什么它会给你一个错误。将它放在 robots.cpp 中是正确的,因此只有 1 个翻译单元(在本例中为 robots.cpp)将具有定义。然后您必须确保 robots.cpp 正在您的项目中编译,以便翻译单元可用于 linker... 因为您可能错误地在源代码中包含 robots.h文件,但永远不要告诉编译器编译 robots.cpp.
在robots.hpp我有一个class
,robots
。我希望每个机器人都有一个指向另一个机器人的指针,即最后声明的那个。我还希望每个人都有一个唯一的 ID。为此,我有一个变量来计算机器人的数量。
看来我无法在 class 定义中初始化我的静态变量。我查找了如何解决该问题,并在 robots.cpp 中找到了一些建议初始化它们的内容。但是,这给了我一个错误,说它们受到保护,所以我不能那样做。所以现在我有一个函数,它在开始时只被构造函数调用一次。
但是,这给了我一个错误,说我不能这样做,因为它们还没有被定义。
robots.hpp中的class定义:
class robot
{
public:
///initialiser.
robot();
[...]
///initialises all robots
void initrobots();
///id of robot
const uint_least8_t id=NumOfRobots++;
static bool hasBeenInitialised;
protected:
///number of robots.
static uint_least8_t NumOfRobots;
///pointer to the next robot that needs pointing to.
static robot* poiRobot;
[...]
///pointer to next robot
robot* nextRobot;
};
robots.cpp:
bool robot::hasBeenInitialised=false;
void robot::initrobots(){
poiRobot=NULL;
NumOfRobots=0;
}
robot::robot(){
if(!hasBeenInitialised){
initrobots();
hasBeenInitialised=true;
}
[...]
}
产生这个错误的代码是这样的:
#include <cstdint>
#include <cstdlib>
class robot
{
public:
///initialiser.
robot();
//[...]
///initialises all robots
void initrobots();
///id of robot
const uint_least8_t id=NumOfRobots++;
static bool hasBeenInitialised;
protected:
///number of robots.
static uint_least8_t NumOfRobots;
///pointer to the next robot that needs pointing to.
static robot* poiRobot;
//[...]
///pointer to next robot
robot* nextRobot;
};
bool robot::hasBeenInitialised=false;
void robot::initrobots(){
poiRobot=NULL;
NumOfRobots=0;
}
robot::robot(){
if(!hasBeenInitialised){
initrobots();
hasBeenInitialised=true;
}
}
int main(){
return 0;
}
如果我编译它,它不会抱怨,但如果我构建它,它就会抱怨(使用 geany 单独做这些事情,c++11 标准(否则 cstdint 抱怨))
我希望代码使 poiRobot
成为指向 null
的指针,并且 NumofRobots
等于 0。
您应该能够摆脱 static bool hasBeenInitialised;
和 bool robot::hasBeenInitialised=false;
以及您的初始化函数,只需直接在您的 cpp 文件中声明 uint_least8_t robot::NumOfRobots = 0;
和 robot* robot::poiRobot = nullptr
。这样他们就会自动将自己初始化为 0 和 null。如评论中所述,这是有效的,受保护的静态变量应该能够以这种方式在源文件中定义。
编辑:关于您在编辑中 post 编辑的代码,您似乎从未定义 robot::poiRobot 和 robot::NumRobots。你试过我在上面 post 编写的代码了吗?
基本上,你项目中的每一个cpp文件都要被编译器编译成一个翻译单元。然后 linker 通过并将所有翻译单元和 links 放在一起。任何看到你的机器人 class 的 cpp 文件都会看到你已经承诺这两个变量存在于某处,因此当你使用它们时它会允许它(就目前而言,它们存在并且有利于走)。当 linker 出现时,它会看到对这些变量的引用,并尝试找到它们在哪个翻译单元中定义,以便它可以完成它的工作(link 一切都在一起)。此时,它不会在任何翻译单元中看到定义,这就是它给您该错误的原因。
uint_least8_t robot::NumOfRobots = 0;
和 robot* robot::poiRobot = nullptr
是您要查找的定义,应该放在您的 cpp 文件中。如果在使用这些之后你得到另一个关于它们被保护的错误,就像你之前暗示的那样,post 那个代码,这样我们就可以看到为什么会发生这种情况。
关于 "It seems that I can't initialise my static variables in the class definition." 的编辑 2:当您将该定义放入头文件中时,包含您的头文件的每个 cpp 文件都将定义它自己的该变量版本。当 linker 转到 link everything 时,它将在不同的翻译单元中看到同一变量的多个定义,这违反了 C++ (ODR) 中的 "One Definition Rule"。这就是为什么它会给你一个错误。将它放在 robots.cpp 中是正确的,因此只有 1 个翻译单元(在本例中为 robots.cpp)将具有定义。然后您必须确保 robots.cpp 正在您的项目中编译,以便翻译单元可用于 linker... 因为您可能错误地在源代码中包含 robots.h文件,但永远不要告诉编译器编译 robots.cpp.