【发布时间】:2021-02-01 02:49:33
【问题描述】:
我正在尝试将来自同一基类的多个不同派生类存储在指针向量中。尝试调用其中一个对象的函数会导致分段错误。我没有经常使用继承,但我已经尝试了我能找到的每个版本,它们要么导致分段错误,要么只是调用基类的函数。
我对 C++ 比较陌生,之前没有发过太多帖子,所以如果我共享太多代码、遗漏任何重要内容或在任何其他方面(风格、效率等)搞砸了,请告诉我.
编辑:getPlayer 函数现在不再尝试返回 Random 或 Human,而是返回一个指示要创建的 Player 类型的 int。新代码仍然会在同一点导致段错误。 (排除 getPlayer,因为它只返回一个 int 并且不再是问题的原因。)
这是我定义基类(Player)和派生类(Human 和 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 );
}
};
这是导致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;
}
【问题讨论】:
-
getPlayer按值返回Player对象。因此,任何返回任何派生类的尝试都注定要失败,因为除了Player之外的所有内容都会被切掉。有关更多信息,请参阅重复的问题。此外,所示代码尝试取消引用未初始化的指针,从而导致未定义的行为。只有一个随机的机会阻止了显示的代码立即在*players[1] = getPlayer(1);行上崩溃。在显示的代码中,有多个与对象在 C++ 中的工作方式相关的基本错误。 -
好的,谢谢。我明白你对这两个问题的意思。我在这里有点超出我的深度,听起来我的整个方法都存在很大缺陷。有没有更好的方法可以用上面的代码来实现我想要实现的目标?我一直在尝试解决问题,但最终使问题变得更加混乱和复杂,并导致更多问题。
-
没有额外的上下文就无法提出有意义的建议。如果这是 C++ 教科书中的一个练习题,那么正确实现它所需的所有必要信息都应该在该章中给出。如果这是一项家庭作业,大概会使用在分配之前在课堂上展示的材料。 “更好的方法”完全取决于这个程序的原始上下文。
-
这是一个长期运行的任务(构建一个简单的奥赛罗或跳棋 AI),大部分细节留给我们。我进行了一些编辑(添加到问题中)以避免您提到的两个问题,但仍然出现段错误。还有其他想法吗?
-
这并没有解决问题,但是一旦你得到这个工作,你会发现
Random::getMove()非常重复。那是因为它在每次调用时都会初始化随机数生成器。在程序开始时只调用一次srand。
标签: c++ pointers inheritance vector segmentation-fault