2016-08-29 27 views
7

Tôi đang cố gắng để kích động một mô hình nhà nước đơn giản, sau khi làm theo một số hướng dẫn tuyệt vời ở đây: http://gameprogrammingpatterns.com/state.htmlnhà nước mẫu C++

Tôi nửa đường qua hướng dẫn hiện hành này, và tôi đang cố gắng để nhân rộng các trường hợp tĩnh của mỗi trạng thái, bằng cách chứa chúng trong lớp cơ sở. Tuy nhiên, khi nói đến trạng thái chuyển đổi, g ++ đang ném lỗi này.

state_test.cpp: In member function ‘virtual void Introduction::handleinput(Game&, int)’: 
state_test.cpp:55:16: error: cannot convert ‘Playing*’ to ‘GameState*’ in assignment 
    game.state_ = &GameState::play; 
       ^

Bây giờ, tôi hiểu lỗi liên quan đến việc chuyển đổi con trỏ, nhưng tôi thực sự đang gặp khó khăn để xem cách khắc phục. Như tôi đã làm theo mã kẻ này, tôi mong đợi nó hoạt động, nhưng bởi vì anh ấy đang thay đổi nó khi anh ấy đi cùng và cố gắng củng cố thực hành tốt nhất, tôi không có mã nguồn hoàn chỉnh của anh ấy để làm theo. Tuy nhiên, tôi cảm thấy điều quan trọng là tôi phải hiểu mã ở giai đoạn này, trước khi tôi chuyển qua phần còn lại của hướng dẫn.

Sau đây là đoạn code tôi tạo ra, cố gắng tái tạo hệ thống nhà nước của mình:

#include <iostream> 

class Game; 
class Introduction; 
class Playing; 

class GameState 
{ 
public: 

    static Introduction intro; 
    static Playing play; 

    virtual ~GameState() {std::cout << "an undefined GameState has been destroyed" << std::endl;} 
    virtual void handleinput(Game& game, int arbitary) {} 
    virtual void update(Game& game) {} 

}; 

class Game 
{ 
public: 

    Game() 
    {} 
    ~Game() 
    {} 

    virtual void handleinput(int arbitary) 
     { 
      state_->handleinput(*this, arbitary); 
     } 

    virtual void update() 
     { 
      state_->update(*this); 
     } 

//private: 
    GameState* state_; 
}; 

class Introduction : public GameState 
{ 
public: 

    Introduction() 
    { 
     std::cout << "constructed Introduction state" << std::endl; 
    } 

    virtual void handleinput(Game& game, int arbitary) 
     { 
      if (arbitary == 1) 
      game.state_ = &GameState::play; 
     } 

    virtual void update(Game& game) {} 
}; 

class Playing : public GameState 
{ 
public: 
    Playing() {std::cout << "constructed Playing state" << std::endl;} 

    virtual void handleinput(Game& game, int arbitary) 
     { 
      if (arbitary == 0) 
      game.state_ = &GameState::intro; 
     } 

    virtual void update(Game& game) {} 
}; 

int main(int argc, char const *argv[]) 
{ 
    Game thisgame; 

    return 0; 
} 

Bất cứ ý tưởng tại sao thực hiện của tôi không được biên dịch?

EDIT:

Vì vậy, để đáp ứng với phần dạy kèm trước đó, tôi rất biết ơn, tôi đã sửa đổi mã. Tôi bắt đầu bằng cách đặt tất cả trong các tệp riêng biệt, nhưng điều này gặp nhiều rắc rối hơn so với giá trị của một lượng nhỏ mã thử nghiệm như vậy. Tôi chỉ đơn giản là viết lại một tập tin tiêu đề mà tuyên bố các lớp học, và sau đó xác định chúng trong tập tin .cpp.

Dưới đây là file .h:

class Introduction; 
class Playing; 
class Game; 
class GameState; 

class GameState 
{ 
    public: 

    static Introduction intro; 
    static Playing play; 

    virtual ~GameState(); 
    virtual void handleinput(Game& game, int arbitary); 
    virtual void update(Game& game); 

}; 


class Introduction : public GameState 
{ 
public: 

    Introduction(); 

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game); 

}; 

class Playing : public GameState 
{ 
public: 
    Playing(); 

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game);  
}; 


class Game 
{ 
public: 

    Game(); 

    ~Game(); 

    virtual void handleinput(int arbitary); 

    virtual void update(); 

    GameState* state_; 

}; 

Và đây là file cpp:

#include <iostream> 
#include "state.h" 


GameState::~GameState() 
    {std::cout << "Exiting Game State Instance" << std::endl;} 
void GameState::handleinput(Game& game, int arbitary) 
    {} 
void GameState::update(Game& game) 
    {} 



Game::Game() 
    {} 
Game::~Game() 
    {} 
void Game::handleinput(int arbitary) 
     { 
      state_->handleinput(*this, arbitary); 
     } 

void Game::update() 
     { 
      state_->update(*this); 
     } 


Introduction::Introduction()  
    { 
     std::cout << "constructed Introduction state" << std::endl; 
    } 

void Introduction::handleinput(Game& game, int arbitary) 
     { 
      if (arbitary == 1) 
      game.state_ = &GameState::play; 
     } 

void Introduction::update(Game& game) {} 


Playing::Playing() 
     { 
      std::cout << "constructed Playing state" << std::endl; 
     } 

void Playing::handleinput(Game& game, int arbitary) 
     { 
      if (arbitary == 0) 
      game.state_ = &GameState::intro; 
     } 

void Playing::update(Game& game) {} 



int main(int argc, char const *argv[]) 
{ 
    Game mygame; 
    return 0; 
} 

Và tôi vẫn không thể có được nó để làm việc. Lỗi trước đó đã biến mất, nhưng tôi đang đấu tranh để truy cập các trường hợp tĩnh của "giới thiệu" và chơi bên trong lớp cơ sở. Lỗi được đưa ra là:

/tmp/ccH87ioX.o: In function `Introduction::handleinput(Game&, int)': 
state_test.cpp:(.text+0x1a9): undefined reference to `GameState::play' 
/tmp/ccH87ioX.o: In function `Playing::handleinput(Game&, int)': 
state_test.cpp:(.text+0x23f): undefined reference to `GameState::intro' 
collect2: error: ld returned 1 exit status 

Tôi nghĩ rằng tôi đã bị hoán đổi! Rất thất vọng!

Tôi nên thêm rằng câu trả lời được cung cấp bởi RustyX biên dịch, tuy nhiên tôi phải di chuyển các trường hợp "đang phát" và "giới thiệu" bên ngoài định nghĩa lớp và sau đó tôi không còn đặt chúng là tĩnh, tôi tin rằng điều này là quan trọng bởi vì tôi chỉ cần một ví dụ của mỗi và tôi muốn chúng được khởi tạo càng sớm càng tốt.

+0

Bạn có thể quan tâm đến khung [STTCL] (https://github.com/makulik/sttcl) của tôi. –

Trả lời

6

Vấn đề là trình biên dịch đọc tệp từ trên xuống dưới. Tại dòng có chứa

game.state_ = &GameState::play; 

ông vẫn không biết rằng Playing thừa hưởng từ GameState. Nó chỉ biết rằng Playing là một lớp sẽ được khai báo sau.

Bạn nên tách các khai báo lớp khỏi triển khai phương pháp. Có tất cả các khai báo lớp đầu tiên và triển khai phương thức sau này. Trong dự án lớn hơn, bạn sẽ chia chúng thành các tệp * .h và * .cpp riêng lẻ và thứ tự này sẽ xảy ra một cách tự nhiên.

rút gọn ví dụ:

class Playing : public GameState 
{ 
public: 
    Playing(); 

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game); 
}; 

// Declarations of other classes... 


Playing::Playing() { 
    std::cout << "constructed Playing state" << std::endl; 
} 

void Playing::handleinput(Game& game, int arbitrary) { 
    if (arbitary == 0) 
     game.state_ = &GameState::intro; 
    } 
} 

void Playing::update(Game& game) { 
} 

Bạn có thể để lại một số các phương pháp bên trong khai báo lớp. Thông thường nó được thực hiện nếu phương pháp là nhỏ, sẽ được hưởng lợi từ nội tuyến và không có loại vấn đề phụ thuộc vòng tròn này.

+0

Ok điều này dường như trả lời câu hỏi của tôi một cách tự tin! Cảm ơn! –

3

Di chuyển việc triển khai các hàm ngoài đường thành sau định nghĩa của tất cả các lớp.

Trình biên dịch phải xem các lớp được kế thừa PlayingIntroduction trước khi nó biết rằng chúng kế thừa từ GameState.

#include <iostream> 

class Game; 
class Introduction; 
class Playing; 

class GameState 
{ 
public: 

    static Introduction intro; 
    static Playing play; 

    virtual ~GameState() {std::cout << "an undefined GameState has been destroyed" << std::endl;} 
    virtual void handleinput(Game& game, int arbitary) {} 
    virtual void update(Game& game) {} 

}; 

class Game 
{ 
public: 

    Game() 
    {} 
    ~Game() 
    {} 

    virtual void handleinput(int arbitary) 
     { 
      state_->handleinput(*this, arbitary); 
     } 

    virtual void update() 
     { 
      state_->update(*this); 
     } 

//private: 
    GameState* state_; 
}; 

class Introduction : public GameState 
{ 
public: 

    Introduction() 
    { 
     std::cout << "constructed Introduction state" << std::endl; 
    } 

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game) {} 
}; 

class Playing : public GameState 
{ 
public: 
    Playing() {std::cout << "constructed Playing state" << std::endl;} 

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game) {} 
}; 

void Introduction::handleinput(Game& game, int arbitary) 
{ 
    if (arbitary == 1) 
     game.state_ = &GameState::play; 
} 

void Playing::handleinput(Game& game, int arbitary) 
{ 
    if (arbitary == 0) 
     game.state_ = &GameState::intro; 
} 

Introduction GameState::intro; 
Playing GameState::play; 


int main(int argc, char const *argv[]) 
{ 
    Game thisgame; 

    return 0; 
} 
Các vấn đề liên quan