对受保护静态成员的未定义引用.我该如何解决

undefined reference to protected static member. How do I solve it?

本文关键字:何解决 解决 静态成员 受保护 未定义 引用      更新时间:2023-10-16

在robots.hpp中,我有一个classrobots。我希望每个机器人都有一个指向另一个机器人的指针,即最后声明的那个机器人。我还希望每个人都有一个唯一的id。为此,我有一个统计机器人数量的变量。

我似乎无法在类定义中初始化我的静态变量。我查了一下如何解决这个问题,发现有人建议在robots.cpp中初始化它们。然而,这给了我一个错误,说它们受到了保护,所以我不能这么做。所以现在我有一个函数,它在一开始只被构造函数调用一次。

但是,这给了我一个错误,说我不能这么做,因为它们还没有定义。

robots.hp:中的类定义

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标准(否则cstilt会抱怨)

我希望代码使poiRobot成为指向null的指针,并且NumofRobots等于0。

您应该能够去掉static bool hasBeenInitialised;bool robot::hasBeenInitialised=false;以及初始化函数,只需在cpp文件中直接声明uint_least8_t robot::NumOfRobots = 0;robot* robot::poiRobot = nullptr。通过这种方式,它们会自动将自己初始化为0和null。正如注释中提到的,这是有效的,受保护的静态变量应该能够以这种方式在源文件中定义。

编辑:关于你在编辑中发布的代码,看起来你从来没有定义robot:poiRobot和robot:NumRobots。你试过我上面发布的代码了吗?

基本上,项目中的每个cpp文件都必须由编译器编译成一个翻译单元。然后链接器通过并获取所有的翻译单元,并将它们链接在一起。任何看到你的robot类的cpp文件都会看到你已经承诺这两个变量存在于某个地方,因此当你使用它们时,它会允许它(就目前而言,它们存在并且很好使用)。当链接器出现时,它会看到对这些变量的引用,并试图找到它们是在哪个翻译单元中定义的,这样它就可以完成自己的工作(将所有内容链接在一起)。在这一点上,它不会在任何翻译单元中看到定义,这就是为什么它会给你这个错误。

uint_least8_t robot::NumOfRobots = 0;robot* robot::poiRobot = nullptr是您要查找的定义,应该放在您的cpp文件中。如果在使用这些代码后,你会发现另一个关于它们受到保护的错误,就像你之前暗示的那样,请发布该代码,这样我们就可以看到为什么会发生这种情况。

编辑2关于"我似乎无法在类定义中初始化我的静态变量。":当你把定义放在头文件中时,每个包含你的头的cpp文件都会定义它自己的变量版本。当链接器链接所有内容时,它将看到同一变量的不同翻译单元中的多个定义,这违反了C++(ODR)中的"一个定义规则"。这就是为什么它会给你一个错误。把它放在robots.cpp中是正确的,所以只有一个翻译单元(在这种情况下是robots.cpp)会有这个定义。然后,你必须确保在你的项目中编译robots.cpp,以便链接器可以使用翻译单元。。。因为你可能会错误地在源文件中包含robots.h,但永远不要告诉编译器编译robots.cpp.