【问题标题】:Scope with Base and Derived Classes in C++C++ 中基类和派生类的作用域
【发布时间】:2016-02-08 08:05:51
【问题描述】:

我很难理解我在这里遇到了什么问题。这是学校课程的作业。我在笔记本电脑上编写代码,然后在学校的服务器上编译/测试/提交。

我目前在 clion 中编写我的代码。当我在我的 Mac 终端上运行 gcc -vg++ -v 时,我得到以下信息:

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

在我得到的学校服务器上运行相同的命令:

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

我正在编译不同版本的 gcc,不确定这是否会影响我的问题。以后...

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 ...
    }

现在,玩家 1 和玩家 2 各自创造了一个准备战斗的生物。注意供以后使用,creature1-&gt;getName() 在这里正常工作。这是战斗循环中给我带来问题的部分。请注意,还有另一个版本,玩家 2 攻击,玩家 1 防御。

    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);

我的 p1Attack 和 p2Attack 有类似的格式:

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

p1Attacks/p2Attacks 工作正常,所有的数学计算都很完美。但是当我在学校服务器上进行战斗时,gcc 4.4.7 20120313 我明白了:

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

第一行不正确,如果他们每个人都创建了相应的字符,则应该是Turn #1, Player 1 (The Barbarian) attacking Player 2 (Reptile)。在我的本地机器上,代码运行正确,并按照应有的方式拼出括号中的名称。

我的生物类和来自于 .setStats() 的示例:

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

所以我的终极问题是,为什么creature1-&gt;getName() 行在我的笔记本电脑和学校服务器上都能正常运行,而在早期if statement,但只能在我的本地机器上运行,而后来无法在远程服务器上运行开启(p1Attack 附近)?

【问题讨论】:

  • Creature *creature1, *creature2; // Objects created。不完全是。创建指针?是的。它们有效吗?不。创建的对象?没有。
  • 你应该为这两个生物分配内存
  • 我觉得你在做一些你没有表现出来的事情。这根本不应该运行,因为正如其他 cmets 所说, bio2 无效。因此,我假设您删除了实际创建此类对象的部分。无论如何,听起来您可能会遇到未定义的行为。一个不接触任何外部资源并且不尝试任何未定义的程序的程序应该在任何地方或多或少地编译相同的。
  • 另外,请不要以这种方式分配对象。如果要从调用堆栈中删除此函数(main() 不可能,但在大多数其他情况下可能),对 newGob1 的任何访问,也称为 *creature1,都将变为未定义。如果你真的知道你在做什么,你应该只获取堆栈分配对象的地址,并且它们真的不应该离开它们所引用的对象的范围。

标签: c++ object reference scope derived-class


【解决方案1】:

如果某样东西在一台机器上运行而在另一台机器上不行,你可以确定你已经成为未定义行为的受害者

确实,您使用的是悬空指针。基本上,归结为:

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

要解决此问题,您需要将对象存储在不受自动内存管理影响的位置(例如在堆上)或重新排列代码以利用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2019-01-17
    • 2016-10-17
    • 2015-06-28
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多