我正在与C++的多态性作斗争。我有两个类,Hero和MainPlayer。Hero是基类,MainPlayer是从Hero派生的。在Hero中,我有一些变量和方法,而MainPlayer有一些附加的变量和方法。我试图创建多态指针,如下所示:
Hero *player = new MainPlayer(constructor);然后,对于播放器,我只能访问Hero类中的方法,否则就会出现编译错误。我想问一下,是否可以通过多态指针:MainPlayer来使用player方法和变量。
我的代码:
class Hero
{
public:
Hero();
virtual void fun() = 0;
private:
int a, b;
};
class MainPlayer:
public Hero
{
public:
MainPlayer();
void fun();
void fun2();
private:
int c;
};
int main()
{
Hero *player = new MainPlayer(constructor);
player->fun(); // works
player->fun2(); //doesn't work
return 0;
}发布于 2017-11-08 18:51:51
从指向基类Hero的指针,您只能调用函数并访问Hero类的成员。
这有一个重要的例外,即在派生类中重写的基类的虚拟函数(具有派生类MainPlayer中描述的相同签名)将调用派生类的实现(即使它不包含关键字override)。
最后,可以将从Hero创建的MainPlayer指针转换回MainPlayer指针,然后可以从MainPlayer调用函数和访问成员,如下面的示例所示:
Hero * h2 = new MainPlayer();
MainPlayer * h3 = dynamic_cast<MainPlayer*>(h2);
if (h3 != nullptr)
{
h3->fun2();
}
delete h2;最后,不要忘记删除分配的指针
编辑:
override说明符虽然不是必需的,但它可以帮助您确保确实正在重写基类中的函数。如果基类没有声明具有相同签名的虚拟函数,程序将不会编译。以下是这个概念的一个简单示例:
struct A
{
virtual void foo();
void bar();
};
struct B : A
{
void foo() const override; // Error: B::foo does not override A::foo
// (signature mismatch)
void foo() override; // OK: B::foo overrides A::foo
void bar() override; // Error: A::bar is not virtual
};发布于 2017-11-08 18:06:05
这是可能的。下面是一个例子。h2是指向Hero的,但是它使用的是来自MainPlayer的方法。
#include <iostream>
#include <string>
class Hero
{
public:
virtual std::string whoAmI() const { return "The Hero"; }
};
class MainPlayer : public Hero
{
public:
std::string whoAmI() const override { return "The Main Player"; }
};
int main()
{
Hero h1;
std::cout << h1.whoAmI() << std::endl;
Hero *h2 = new MainPlayer;
std::cout << h2->whoAmI() << std::endl;
return 0;
}指纹:
The Hero
The Main Player发布于 2017-11-08 18:18:12
当通过指向MainPlayer的指针访问Hero时,唯一公开的接口是Hero接口,编译器只能利用Hero已知的功能。
如何绕过这一问题(按我个人的喜好排列):
在需要MainPlayer额外功能的情况下,避免以Hero的形式与MainPlayer进行交互。MainPlayer和其他所有人一样,会受到攻击和损害(或多或少都要归功于覆盖的可能性),但如果只有MainPlayer可以使用SwingFromChandelier,那么应该为MainPlayer提供这样做的机会。在这种情况下,MainPlayer在大多数情况下都可以作为MainPlayer使用。
摘要消除了公开附加功能的需要。例如,也许MainPlayer::fun可以调用MainPlayer::fun2来执行额外的MainPlayer操作。MainPlayer对Hero::Attack的覆盖可以调用BerserkRampage专用攻击函数,从而消除了向任何人公开BerserkRampage的需要。
Hero的接口可能是未指定的.考虑使用附加的虚拟函数扩展Hero。
dynamic_cast Hero * to MainPlayer *,验证结果不是nullptr,并在新创建的MainPlayer *上调用MainPlayer功能。
https://stackoverflow.com/questions/47186497
复制相似问题