2017-01-03 7 views
1

robots.hpp에서 나는 class, robots입니다. 각 로봇에게 마지막으로 선언 된 로봇에 대한 포인터를 갖기를 원합니다. 나는 또한 각각이 유일한 ID를 갖고 싶어한다. 이를 위해 로봇 수를 세는 변수가 있습니다.보호 된 정적 멤버에 대한 참조가 정의되지 않았습니다. 어떻게 해결합니까?

클래스 정의에서 정적 변수를 초기화 할 수없는 것 같습니다. 나는 그것을 해결하는 방법을 찾아 보았고, 로봇에서 로봇을 초기화하는 것을 추천했다. 그러나, 그것은 나에게 그들이 보호 받고있다라고 말하는 오류를 준다. 그래서 나는 그것을 할 수 없다. 그래서 지금은 처음에 생성자에 의해 한 번만 호출되는 함수가 있습니다.

그러나 아직 정의되지 않았기 때문에 내가 할 수 없다는 오류가 발생합니다.

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; 
} 

내가 컴파일하는 경우 그것은 불평하지 않지만 내가 그것을 구축하면 불평을한다. (물건을 별도로 처리하기 위해 geany를 사용한다. cstdint는

내가 nullpoiRobot 포인터를 만들기 위해 코드를 원하는, 그리고 NumofRobots 동일한

+3

회원을 초기화하는 방법을 보여줄 수있는 곳에 [mcve]를 만들 수 있습니까? – NathanOliver

+0

방금'class Test {protected : static int x; }; int Test :: x = 2;'GCC에서 잘 작동합니다. – Frank

+1

보호는 전혀 중요하지 않습니다. 'robot * robot :: poiRobot; '는'hasBeenInitialised'의 정의와 마찬가지로 작동해야합니다. 그렇지 않으면 오류 메시지의 사본과 함께 오류를 생성하는 코드를 게시하십시오 (바꾸지 말고 복사 및 붙여 넣기 사용). – molbdnilo

답변

0

0으로 당신은 static bool hasBeenInitialised;bool robot::hasBeenInitialised=false;뿐만 아니라 초기화 함수 그냥 제거 할 수 있어야한다)) 불평 귀하의 cpp 파일에 직접 uint_least8_t robot::NumOfRobots = 0;robot* robot::poiRobot = nullptr을 선언하십시오. 이렇게하면 자동으로 0으로 초기화되고 null이됩니다. 주석에서 언급했듯이 유효하며 보호 된 정적 변수는이 방식으로 소스 파일에 정의 될 수 있어야합니다.

편집 : 편집에 게시 한 코드와 관련하여 로봇 : poiRobot 및 robot :: NumRobots을 절대로 정의하지 않은 것처럼 보입니다. 위에 게시 한 코드를 사용해 보셨습니까?

기본적으로 프로젝트의 각 cpp 파일은 컴파일러에서 번역 단위로 컴파일해야합니다. 그런 다음 링커가 들어 와서 번역 단위를 모두 가져 와서 연결합니다. 로봇 클래스를 보는 모든 cpp 파일은 그 두 변수가 어딘가에 있다고 약속했음을 알게 될 것이므로 사용하면 그것을 허용 할 것입니다. 링커가 나타나면 변수에 대한 참조가 표시되고 정의 된 변환 단위를 찾아서 작업을 수행 할 수 있습니다. 이 시점에서 모든 번역 단위에서 정의가 표시되지 않으며 그 이유 때문에 오류가 발생합니다.

uint_least8_t robot::NumOfRobots = 0;robot* robot::poiRobot = nullptr은 찾고 계신 정의이며 cpp 파일에 들어 있어야합니다. 그 코드를 사용하고 나면 이전에 암시 한 것처럼 보호 받고있는 다른 오류가 발생하면 그 코드를 게시하여 왜 그런 일이 발생하는지 알 수 있습니다.

"클래스 정의에서 내 정적 변수를 초기화 할 수없는 것 같습니다.": 헤더 파일에 해당 정의를 넣으면 머리글을 포함하는 각 cpp 파일에 자체 버전이 정의됩니다 그 변수의.링커가 모든 것을 링크 할 때 동일한 변수에 대해 여러 번역 단위에서 여러 정의를 볼 수 있으며 C++ (ODR)의 "하나의 정의 규칙"을 위반합니다. 그래서 그것이 당신에게 오류를 줄 것입니다. robots.cpp에 두는 것이 옳습니다. 따라서이 경우 번역 단위 (이 경우 robots.cpp) 만 정의됩니다. 그럼 당신은 robots.cpp가 당신의 프로젝트에서 컴파일되어서 번역기가 링커에서 사용 가능하도록 컴파일해야합니다 ... 당신이 실수로 robots.h를 소스 파일에 포함시킬 수는 있지만 컴파일러에게 결코 컴파일하지 말라고 할 수는 있습니다 robots.cpp.

+1

영업 사원이 그랬지만 오류가 발생했습니다. 실제로 진행되고있는 작업을 알기 전에 오류를 포함한 mcve를 제공하기 위해 영업을해야합니다. – NathanOliver

+0

@MarkGardner가 귀하의 편집과 관련하여 업데이트되었습니다 – RyanP

+0

나는 그것들이 정적이 아니고 일정해야합니다. 그리고 저는 로봇을 컴파일하도록 말합니다. –