2017-01-03 14 views
1

robots.hppにはclass,robotsがあります。私は各ロボットに、最後に宣言された別のロボットへのポインタを持たせたい。私はまた、それぞれが一意のIDを持つことを望みます。これには、ロボットの数を数える変数があります。保護された静的メンバーへの未定義参照。どうすれば解決できますか?

私はクラス定義で静的変数を初期化できないようです。私はそれを解決する方法を探し、ロボットでそれらを初期化することを推奨するものを見つけました。しかし、それは私に彼らが保護されているというエラーを与え、私はそれをすることができません。だから私は最初にコンストラクタによって一度だけ呼び出される関数を持っています。

しかし、それはまだ定義されていないので、私はそれができないと言っているエラーを私に与えています。私はそれをコンパイルする場合

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

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; 
    } 
[...] 
} 

このエラーを生成するコードはこれですそれは文句を言うことはありませんが、私はそれを構築すると文句を言うことはありません。 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ファイルは、あなたがそれらの2つの変数がどこかに存在すると約束したことを見るでしょう。したがって、あなたがそれらを使用すると、それが許されます(懸念されている限り、リンカーが表示されたら、それらの変数への参照が表示され、定義されている翻訳単位を見つけようとします(すべてをリンクする)。この時点では、どの翻訳単位でも定義が表示されないため、そのエラーが発生します。

uint_least8_t robot::NumOfRobots = 0;およびrobot* robot::poiRobot = nullptrは、探している定義であり、cppファイルに入れる必要があります。それらを使用した後に、あなたが以前に示唆したように保護されているという別のエラーが発生した場合は、そのコードを投稿して、なぜそれが起こっているのかを見ることができます。

「クラス定義で静的変数を初期化できないようです」:ヘッダーファイルにその定義を入れると、ヘッダーを含む各cppファイルには独自のバージョンが定義されますその変数のリンカーがすべてをリンクすると、同じ変数の異なる翻訳単位で複数の定義が表示され、C++(ODR)の「One Definition Rule」に違反します。それがあなたに誤りを与える理由です。 robots.cppに入れるのは間違いありません。そのため、1つの翻訳単位(この場合はrobots.cpp)のみが定義されます。次に、あなたのプロジェクトでrobots.cppがコンパイルされていることを確認して、翻訳ユニットがリンカのために利用できるようにしなければなりません。誤ってあなたのソースファイルにrobots.hを含めることはできますが、 robots.cpp。

+1

OPはこれをしたと言っていますが、エラーが発生しました。実際に何が起こっているかを知る前に、エラーを含むmcveを提供するためにOPをする必要があります。 – NathanOliver

+0

@MarkGardnerがあなたの編集に関して更新されました – RyanP

+0

私は静的で非定数である必要があります。そして私はロボットをコンパイルするように言います。 –

関連する問題