我正在使用C ++与SDL库进行游戏,并且遇到了多态性问题。我的项目包含很多代码,所以我会尽量使用一个例子。
我有一个基类Pawn
和派生类Knight
和Mage
。 Pawn
包含Knight
和Mage
使用的功能,但Knight
和Mage
具有特定于自身的功能。
让我们说Pawn
有一个函数move()
,而Knight
和Mage
每个都有一个函数attack()
,它们为每个函数执行不同的操作。我创建了一个对象selectedPawn
,以便在Knight
和Mage
之间点击并选择每个对象。
Knight* knight = new Knight();
Mage* mage = new Mage();
Pawn* selectedPawn = new Pawn();
selectedPawn = knight;
selectedPawn->move(); //This does not give me any errors and runs as it should.
selectedPawn->attack(); //Error: class "Pawn" has no member "attack"
我的问题是,有没有办法让这成为可能?如果没有,我是否完全错过了多态的目的或以错误的方式执行它?
答案 0 :(得分:2)
您的基类定义界面
struct Pawn
{
virtual void move() = 0;
virtual void attack(Pawn*) = 0;
virtual ~Pawn() = default;
};
您的派生类实现该接口,为每个函数实现自己的特定细节
struct Knight : Pawn
{
void move() override;
void attack(Pawn*) override;
};
struct Mage : Pawn
{
void move() override;
void attack(Pawn*) override;
};
现在您可以在基类指针上调用这些函数,但由于多态,将调用派生函数,因此特定于该派生实例的函数
Pawn* piece1 = new Knight;
Pawn* piece2 = new Mage;
piece1->move(); // will call Knight::move
piece2->move(); // will call Mage::move
如果它变得有用,你可以使用一个Pawn
指针的函数,它不知道它是Knight
还是Mage
,但是因为多态性,正确的函数被称为
void do_move(Pawn* piece)
{
piece->move();
}
void do_attack(Pawn* aggressor, Pawn* piece)
{
aggressor->attack(piece);
}
piece1->attack(piece2); // Knight attacks Mage
piece2->attack(piece1); // Mage attacks Knight
答案 1 :(得分:2)
您无法在C ++中执行此操作(您可以在一些Smalltalk派生的语言中执行此操作)
您可能想要做的是创建另一个类Attacker,将Attack方法作为纯虚方法。
让骑士和法师来自攻击者以及典当。
使用selectedPawn上的dynamic_cast运算符尝试从中获取攻击者指针。如果攻击者*非空,您可以使用它在selectedPawn上调用attack()。
Attacker* attacker = dynamic_cast<Attacker*>(selectedPawn);
if (attacker) {
attacker->attack();
}