首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多态指针

多态指针
EN

Stack Overflow用户
提问于 2017-11-08 17:53:58
回答 3查看 2.7K关注 0票数 1

我正在与C++的多态性作斗争。我有两个类,HeroMainPlayerHero是基类,MainPlayer是从Hero派生的。在Hero中,我有一些变量和方法,而MainPlayer有一些附加的变量和方法。我试图创建多态指针,如下所示:

代码语言:javascript
复制
Hero *player = new MainPlayer(constructor);

然后,对于播放器,我只能访问Hero类中的方法,否则就会出现编译错误。我想问一下,是否可以通过多态指针:MainPlayer来使用player方法和变量。

我的代码:

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-08 18:51:51

从指向基类Hero的指针,您只能调用函数并访问Hero类的成员。

这有一个重要的例外,即在派生类中重写的基类的虚拟函数(具有派生类MainPlayer中描述的相同签名)将调用派生类的实现(即使它不包含关键字override)。

最后,可以将从Hero创建的MainPlayer指针转换回MainPlayer指针,然后可以从MainPlayer调用函数和访问成员,如下面的示例所示:

代码语言:javascript
复制
Hero * h2 = new MainPlayer();
MainPlayer * h3 = dynamic_cast<MainPlayer*>(h2); 

if (h3 != nullptr)
{
    h3->fun2();
}

delete h2;

最后,不要忘记删除分配的指针

编辑:

override说明符虽然不是必需的,但它可以帮助您确保确实正在重写基类中的函数。如果基类没有声明具有相同签名的虚拟函数,程序将不会编译。以下是这个概念的一个简单示例:

代码语言:javascript
复制
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
};
票数 3
EN

Stack Overflow用户

发布于 2017-11-08 18:06:05

这是可能的。下面是一个例子。h2是指向Hero的,但是它使用的是来自MainPlayer的方法。

代码语言:javascript
复制
#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;
}

指纹:

代码语言:javascript
复制
The Hero
The Main Player
票数 3
EN

Stack Overflow用户

发布于 2017-11-08 18:18:12

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

如何绕过这一问题(按我个人的喜好排列):

在需要MainPlayer额外功能的情况下,避免以Hero的形式与MainPlayer进行交互。MainPlayer和其他所有人一样,会受到攻击和损害(或多或少都要归功于覆盖的可能性),但如果只有MainPlayer可以使用SwingFromChandelier,那么应该为MainPlayer提供这样做的机会。在这种情况下,MainPlayer在大多数情况下都可以作为MainPlayer使用。

摘要消除了公开附加功能的需要。例如,也许MainPlayer::fun可以调用MainPlayer::fun2来执行额外的MainPlayer操作。MainPlayerHero::Attack的覆盖可以调用BerserkRampage专用攻击函数,从而消除了向任何人公开BerserkRampage的需要。

Hero的接口可能是未指定的.考虑使用附加的虚拟函数扩展Hero

dynamic_cast Hero * to MainPlayer *,验证结果不是nullptr,并在新创建的MainPlayer *上调用MainPlayer功能。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47186497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档