C++ 对受保护静态成员的未定义引用。我如何解决它?

C++ 对受保护静态成员的未定义引用。我如何解决它?,c++,class,g++,linker-errors,C++,Class,G++,Linker Errors,在robots.hpp中,我有一个类,机器人。我希望每个机器人都有一个指向另一个机器人的指针,这个机器人是最后声明的。我还希望每个人都有一个唯一的id。为此,我有一个变量来计算机器人的数量 似乎我无法在类定义中初始化静态变量。我查阅了如何解决这个问题,发现了一些建议在robots.cpp中初始化它们的内容。然而,这给了我一个错误,说他们是受保护的,所以我不能这样做。现在我有了一个函数,构造函数在开始时只调用一次 然而,这给了我一个错误,我不能这么做,因为它们还没有定义 robots.hpp中的类

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

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

然而,这给了我一个错误,我不能这么做,因为它们还没有定义

robots.hpp中的类定义:

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;
}
#包括
#包括
班级机器人
{
公众:
///初始化器。
机器人();
//[...]
///初始化所有机器人
void initrobots();
///机器人id
constuint_least8_t id=NumOfRobots++;
静态布尔值已初始化;
受保护的:
///机器人的数量。
静态单元至少8个机器人;
///指向需要指向的下一个机器人的指针。
静态机器人;
//[...]
///指向下一个机器人的指针
机器人*nextRobot;
};
bool robot::hasBeenInitialised=false;
void robot::initrobots(){
poi=NULL;
数值=0;
}
robot::robot(){
如果(!已初始化){
初始化机器人();
hasBeenInitialised=true;
}
}
int main(){
返回0;
}
如果我编译它,它不会抱怨,但是如果我构建它,它会抱怨(使用geany单独完成这些事情,c++11标准(否则cstdint会抱怨))


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

您应该能够摆脱
静态bool已初始化
bool robot::hasBeenInitialised=false以及您的初始化函数,只需声明
uint\u least8\u t robot::numorbots=0
robot*robot::poiRobot=nullptr
直接在您的cpp文件中。这样,它们会自动将自己初始化为0和null。如注释中所述,这是有效的,受保护的静态变量应该能够以这种方式在源文件中定义

编辑:关于您在编辑中发布的代码,看起来您从未定义robot::poiRobot和robot::NumRobot。你试过我上面贴的代码了吗

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

uint\u least8\u t robot::NumOfRobots=0
robot*robot::poiRobot=nullptr
是您要查找的定义,应该放在您的cpp文件中。如果在使用这些代码之后,您得到了另一个错误,即您之前暗示过的关于它们受到保护的错误,那么请发布该代码,以便我们了解发生这种情况的原因


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

您应该能够摆脱
静态bool未初始化
bool robot::hasBeenInitialised=false以及您的初始化函数,只需声明
uint\u least8\u t robot::numorbots=0
robot*robot::poiRobot=nullptr
直接在您的cpp文件中。这样,它们会自动将自己初始化为0和null。如注释中所述,这是有效的,受保护的静态变量应该能够以这种方式在源文件中定义

编辑:关于您在编辑中发布的代码,看起来您从未定义robot::poiRobot和robot::NumRobot。你试过我上面贴的代码了吗

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