多态指针

时间:2017-11-08 17:53:58

标签: c++ oop pointers polymorphism

我正在努力克服C ++中的多态性。我有2个班级,HeroMainPlayerHero是基类,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;
}

3 个答案:

答案 0 :(得分:3)

有可能。这是一个例子。 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

答案 1 :(得分:2)

当通过指向MainPlayer的指针访问Hero时,唯一公开的接口是Hero的接口,并且编译器只能利用{{1}已知的功能}。

如何解决这个问题(按个人喜好排序):

在需要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 *MainPlayer *,验证结果不是nullptr,并在新建的MainPlayer上调用MainPlayer *功能

答案 2 :(得分:2)

从指向基类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
};