简体   繁体   中英

Scope with Base and Derived Classes in C++

I am struggling to understand what issue I am having here. This is an assignment for a course at school. I write my code on my laptop, and compile/test/submit it on the school's server.

I currently write my code in clion. When I run gcc -v or g++ -v on my Mac's terminal I get the following:

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin15.0.0

Running the same command on the school's server I get:

gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)

I'm compiling on different version of gcc, not sure if that influences my issue. Onwards...

int main() {
    int choice; // Used to get creature selection from user
    Creature *creature1, *creature2; // Objects created

    printCreatureList(); // Prints list of creatures for players to select from

    choice = getIntFromUser(5); // Gets user choice for creature selection
    if (choice == 1) {
        Goblin newGob1;
        creature1 = &newGob1;
        newGob1.setStats();

        cout << "Created " << creature1->getName() << " as player 1's creature.\n";
// more if-else, and repeat for player 2 ...
    }

Now, player 1 and player 2 each have a creature created that is ready to fight. Note for later use, creature1->getName() functions correctly here. Here is the portion of the fight loop that gives me an issue. Note that there is another version of this where player 2 attacks, and player 1 defends.

    do { // Enter game loop
        cout << endl << "\nTurn #" << i << ", Player 1 (" << creature1->getName() << ") attacking Player 2 (" << creature2->getName() << ")";
        i++;

        p1Attacks(*creature1, *creature2, *p1Achilles, *p2Achilles); // Player 1 attacks, player 2 defends

        if (creature2->getStrength() <= 0) { //Check if creature2 was defeated
            cout << "\n\t***Player 2's creature has taken fatal damage***" << endl;
            cout << "\n\t* * * Player 1 (" << creature1->getName() << ") has won the battle * * *" << endl;
            winCondition = false;
            break;

       // advances on to p2Attacks
     } while (winCondition);

My p1Attack and p2Attack have similar formats:

void p1Attacks(Creature &p1, Creature &p2, bool &p1AchillesInjury, bool &p2AchillesInjury)

the p1Attacks/p2Attacks work correctly, and all the math comes out perfect. But when I run the fight on my schools server, gcc 4.4.7 20120313 I see:

Turn #1, Player 1 () attacking Player 2 () Player 1's attack roll: 7 Player 2's defend roll: 1 Player 1's damage output: 6 Player 2's armor: 3 Player 2 damage taken: 3 Player 2 new strength: 5

The first line is incorrect, it should read Turn #1, Player 1 (The Barbarian) attacking Player 2 (Reptile) if they each created those respective characters. On my local machine, the code runs correct and spells out the names in parentheses as it should.

My creature class and an example of .setStats() from creature.cpp:

class Creature {
public:
    Creature() {}
/*
    Functions:      changeStrength()
    Description:    Change strength attribute for creature by reducing value
    Parameters:     reduceStrengthBy
    Preconditions:  None
    Postconditions: Strength is reduced
*/
    void changeStrength(int reduceStrengthBy);

    int getAttackDice()     { return attackDice; }
    int getAttackSides()    { return attackSides; }

    int getDefenseDice()    { return defenseDice; }
    int getDefenseSides()   { return defenseSides; }

    int getArmor()          { return armor; }
    int getStrength()       { return strength; }

    std::string getName()   { return name; }

    bool getDodge()         { return dodge; }

protected:
    int attackDice;
    int attackSides;

    int defenseDice;
    int defenseSides;

    int armor;
    int strength;

    std::string name;

    bool dodge;
};

void Reptile::setStats() {
    attackDice = 3;
    attackSides = 6;
    defenseDice = 1;
    defenseSides = 6;
    armor = 7;
    strength = 18;
    name = "The Reptile";
    dodge = false;
}

So my ultimate question is, why does the line creature1->getName() function correctly on both my laptop and the schools server while in the early if statement , but only work on my local machine and fail to work on the remote server later on (near p1Attack)?

If something works on one machine but not another you can be sure that you've become victim of undefined behaviour .

And indeed, you're using dangling pointers. Basically, it boils down to this:

int main(int, char**) {
  int * pointer; // uninitialised, don't use
  if (someCondition) {
    int object = 42;
    pointer = &object; // assigned to point to an object, can be used
  } // object goes out of scope here
  // pointer is dangling, don't use
  cout << *pointer << endl; // oops
  return 0;
}

To solve this you need to either store your objects where they're not subject of automatic memory management (eg on the heap) or rearrange your code to take advantage of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM