user2324350
user2324350

Reputation: 37

Why isn't the derived-class version of the function being called?

I'm trying to store multiple different derived classes from the same base class in a vector of pointers. Trying to call a function of one of those objects results in a segmentation fault. I haven't used inheritance very much, but I've tried every version I've been able to find and they either result in a segmentation fault or just calls the function of the base class.

I'm relatively new to C++ and haven't posted much before so please let me know if I'm sharing too much code, missing anything important, or messing up in any other respect (style, efficiency, etc.).

Edit: Instead of trying to return a Random or Human, the getPlayer function now just returns an int which which indicates which type of Player to create. The new code still results in a seg fault at the same point. (excluded getPlayer since it just returns an int and can no longer be the cause of the problem.)

This is where I define the base class (Player) and derived classes (Human and Random):

#include <string>
#include <iostream>
#include <limits>
#include <time.h>
#include "Othello.h"
using namespace std;

// Player interface to choose game moves
class Player {
public:
    // Selects and returns a move 
    virtual int getMove(Othello &game) {
        return 0;
    }
};

// User-operated player
class Human: public Player {
public:
    int getMove(Othello &game) {
        int move = 0;
        bool valid= false;
        
        while (!valid) {
            cout << "Select a move: " << endl;
            cout << "-> ";
            cin >> move;
            
            if (cin.good()) { valid = true; }
            
            else {
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(),'\n');
                cout << "Invalid input. Try again.\n" << endl;
            }
        }
        return move;
    }
};

// Basic bot - selects a move at random
class Random: public Player {
public:
    int getMove(Othello &game) {
        srand(time(NULL));
        return ( 1 + rand() % game.n_moves );
    }
};

Here is the main function which results in a seg fault at the line move = players[state-1]->getMove(game):

int main() {
    
    // Select players (human, AI, random, etc.)
    // players[0] is left empty to keep the index consistent with the player id
    vector<Player*> players(2);
    int type;
    for ( int i : {1, 2} ) {
        type = getPlayer(i);
        if (type == 1) { players.push_back( new Human() ); }
        else if (type == 2) { players.push_back( new Random() ); }
    }
    
    // Load and start the game
    Othello game = loadBoard();
    int state = game.getState(1); // 1 or 2 for turn, or 0 for game over
    
    // Continue making moves until the game ends
    int move;
    int legal;
    while(state != 0) {
        game.print();
        legal = 0;
        cout << "PLAYER " << game.turn << endl;
        while (legal == 0) {
            move = players[state-1]->getMove(game);
            legal = game.doMove(move);
        }
        state = game.getState();
    }
    
    game.print();
    game.score();
    
    return 1;
}

Upvotes: 0

Views: 125

Answers (1)

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32727

vector<Player*> players(2); declares a vector with two elements that will both be default initialized to nullptr.

Later, you add two more elements, so that players has 4 elements.

When state has a value of 1 or 2, the call to players[state-1]->getMove(game); will dereference a null pointer, resulting in your segmentation fault.

You likely want to define players to initially be empty (vector<Player*> players;), and update the comment on the line before this definition. (That comment, in its current form, seems to make no sense with how you're accessing the players vector later.)

Upvotes: 1

Related Questions