2015-11-05 5 views
0

Я пытаюсь сделать очень простой язык программирования, который позволяет кому-то играть в игру линкора для школьного проекта в Flex/Bison. Чтобы сохранить мои переменные, у меня есть карта с именем symbol_table, которая берет строку для ключа и имеет переменную * для ее значения. Дерево наследования выглядит следующим образом:Указатель базового класса динамического класса C++ для указателя производного класса

class Expression { 
public: 
    Type type; 
    virtual ~Expression(){} //to make it polymorphic 
}; 

class Variable : virtual public Expression { 
public: 
    char* name; 
    Variable* next; 

    virtual ~Variable(){ //also for polymorphism 
     delete name; 
     delete next; 
    } 
}; 

class Player : virtual public Variable{ 
public: 
    std::string playerName; 
    std::vector<GameBoat> playerBoats; 
    Grid opponentGrid; 
    Grid playerGrid; 

    Player(std::string playerName){ 
     this->playerName = playerName; 
    } 

    bool addBoat(std::string boatName, char scolumn, int srow, bool vertical){ 
     //make new boat here and then push it back to the vector 
     GameBoat newBoat(boatName);   //this works --> makes a valid boat 
     if(newBoat.assignedValue){ 
      playerBoats.push_back(newBoat); //SEGMENTATION FAULT HAPPENS HERE 
      return true; 
     }else{ 
      return false; 
     } 
    } 
}; 

class Computer : public Player{ 
public: 
    Computer(std::string playerName) : Player(playerName){} 
}; 

Все прекрасно работает, когда я ставлю указатели игрока и компьютерные указатели на карту, но когда я пытаюсь получить эти значения еще раз, используя dynamic_cast, чтобы обратное приведение базовых переменные * Игрок * или Компьютер *, все атрибуты литого игрока * или компьютера * являются NULL и, таким образом, дают мне ошибку «Ошибка сегментации: 11». Тем не менее, я могу получить доступ к методам класса, которые находятся в классах Player и Computer.

Variable* var = get_symbol($1); 

    if (var == NULL) { 
     sprintf(errormsg, "%s not found.\n", $1); 
     yyerror(errormsg); 
    }else if(var->type == PlayerType){ 
     Player* myPlayer = dynamic_cast<Player*>(var);  //Cast var to Player* 
     myPlayer->addBoat("aircraftcarrier", 'a', 1, true); //Enters this function 
    }else if(var->type == ComputerType){ 
     Computer* myComputer = dynamic_cast<Computer*>(var); //Cast var to Computer* 
     myComputer->addBoat("aircraftcarrier", 'a', 1, true); //Enters this function 
    } 

Как я могу получить доступ к методам производного класса, но не иметь доступа к атрибутам производного класса? Я использую полиморфизм, а dynamic_cast не возвращает значение NULL (иначе программа никогда не войдет в функции и сразу же не получит ответ сегментации).

+0

Вы создаете язык программирования только для создания игры с линкорами? –

+0

Это школьный проект. это кроме того. – tdon

+1

Можете ли вы предоставить [минимальный, полный и проверяемый пример] (http://www.stackoverflow.com/help/mcve)? Я не знаю, в чем проблема. – Barry

ответ

0

Функция addBoat не является виртуальной, поэтому перед ее вызовом не требуется разыгрывать myPlayer или myComputer, поэтому вы не получите segfault дольше в функции.

Все функции-члены имеют неявный параметр this. Вы можете думать о addBoat как эквивалент свободной функции bool addBoat(Player* this, std::string boatName, char scolumn, int srow, bool vertical). Нет ничего особенного в том, что является NULL или нет, пока вы на самом деле не разыщите его в функции.

Для решения возникшей проблемы вы должны проверить, что myPlayer и myComputer не являются NULL перед вызовом функции.

+0

Если 'this' NULL, произошло что-то плохое. –

+0

Да, очевидно, но это не является разыменованием для вызова функции-члена. Вот почему segfault происходит позже – Kevin

+0

Это разыменовывается. 'mem_func();' is 'this-> mem_func();' –

Смежные вопросы