【问题标题】:How to access member in derived classes by a pointer of type base but pointing to the derived class如何通过基类型的指针访问派生类中的成员但指向派生类
【发布时间】:2016-10-03 21:20:09
【问题描述】:

我有以下代码:

#include <iostream>
using namespace std;

class Weapon
{
protected:
    int strength;
    char type;
public:
    int modified;

    int return_strength()
    {
        return strength;
    }

    char return_type()
    {
        return type;
    }

    void setPower (int val)
    {
        strength = val;
        return;
    }
};



class Rock: public Weapon
{

public:
    Rock()
    {
        type='r';
    }
    bool battle(Weapon w)
    {
        //Write your solution code below this line

        //default return statement below

        switch ( w.return_type() ) {
            case 'p':
                modified   = strength / 2;
                w.modified = strength * 2;
                break;
            case 's':
                modified   = strength * 2;
                w.modified = strength / 2;
                break;
            default:
                cout << "Unkown option";
                break;
        }

        if (modified > w.modified )
        {
            return true;
        }
        else if (modified < w.modified )
        {
            return false;
        }
        else
        {
            cout << "The strenghs are equal";
            return -1;
        }
    }

};

class Paper: public Weapon
{

public:
    Paper()
    {
        type='p';
    }
    bool battle(Weapon w)
    {
        //Write your solution code below this line

        //default return statement below
        return true;
        //remove the default return statement and return your own result

    }

};

class Scissors: public Weapon
{

public:
    Scissors()
    {
        type='s';
    }
    bool battle(Weapon w)
    {
        //Write your solution code below this line

        //default return statement below
        return true;
        //remove the default return statement and return your own result


    }

};



int main()
{
    char play1, play2, str_winner;
    int  str1, str2;
    bool winner;
    Paper obj_paper;
    Rock  obj_rock;
    Scissors obj_scissors;
    Weapon *p1, *p2;


    cout << "1st player: Choose Rock (r), Paper (p) or Scissors (s)";
    cin  >> play1;
    cout << "Insert a strength";
    cin  >> str1;
    cout << "2st player: Choose Rock (r), Paper (p) or Scissors (s)";
    cin  >> play2;
    cout << "Insert a strength";
    cin  >> str2;

    switch( play1 ){
        case 'r':
           p1 = &obj_rock;
        case 'p':
           p1 = &obj_paper;
        case 's':
           p1 = &obj_scissors;
    }

    switch( play2 ){
        case 'r':
           p2 = &obj_rock;
        case 'p':
           p2 = &obj_paper;
        case 's':
           p2 = &obj_scissors;
    }

    p1->setPower(str1);
    p2->setPower(str2);

    winner = p1->battle(*p2);

    return 0;
}

代码还没有完全完成,但我面临两个问题。

1) 当我尝试从派生类之一访问战斗时,它说没有该名称的成员。似乎 p1 只能访问基类。当我让指针指向派生类时,c++ 现在是否允许我访问派生类中的函数?

2) 有没有更好的方法来确定我应该在运行时使用哪个派生类。如您所见,我从用户那里得到两个输入,告诉他他想要什么武器,然后我需要指出要考虑的对象。

谢谢

【问题讨论】:

    标签: c++ inheritance polymorphism


    【解决方案1】:
    1. 从派生类之一访问战斗;这就是 p1 的类型 武器成员没有战斗。您可能还希望查找“虚拟”关键字。 (Java、C# 和其他 OO 语言默认应用此关键字)另外值得一读的是纯虚函数。

    2.

     switch(play1 ){
            case 'r':
               p1 = &obj_rock; 
    
     ...
    

    虽然你正在做的事情很好,但我认为你想要做的是 p1 = new Rock() {当你用完那段记忆后,再删除 p1}。

    这也是一个更普遍的问题,人们使用factory pattern

    【讨论】:

    • 我对virtual很熟悉,但是我不知道如何在这里使用它。因为插入 virtual bool Battle(Weapon w) 会产生编译错误,因为它不能与类类型有相同的参数,对吧?
    • Wrong :) virtual 仅意味着从它派生的类可以有自己的实现,并且应该默认调用。您可以在该函数中使用任何您喜欢的参数,包括基类。因此类 A {void x(A x){}};是一个有效的类和函数
    • 你是对的。我尝试的是做一个抽象实现,即虚拟布尔战斗(武器 w)= 0;。我这样做是因为对我来说这很方便,因为我不会在基类中做任何事情。但是为什么这不起作用呢?
    • 虚拟布尔战斗(武器 w) = 0;这是一个纯虚函数;这正是你所追求的!您尝试使用时遇到了什么错误?
    • AHHH - 是的,问题是您试图将 Weapon 作为具体值传递;而您要做的是传入引用或指针。尝试虚拟布尔战斗(武器* w)然后 p1->battle(p2)
    【解决方案2】:

    你可以对派生类做一个安全的dynamic_cast,如果它不为null,那么调用你的派生类方法

    我会向基类添加一个虚拟方法或纯方法或默认实现,并让每个武器重载它。

    【讨论】:

    • 这是一个糟糕的解决方案。相反,Weapon 应该有一个被多态调用的 virtual 方法。你不应该只尝试一堆dynamic_cast,直到一个工作。
    • 我正想说这是一个糟糕的设计 :)
    • 你的意思是我在我的 Weapon 类中添加了一个“virtual bool Battle(Weapon w)”。但是是否有可能有与类相同类型的论点
    • 是的,你可以。我会让虚拟布尔战斗(武器和w)通过参考甚至虚拟布尔战斗(const Weapon& w)。因为您不会更改传入的 w 对象。如果你不能这样做,那么你就不能定义像 = 或 - 或 + 这样的运算符来接收相同类型的其他对象;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 2020-02-11
    • 2011-01-27
    • 2015-02-04
    • 2021-08-05
    • 2017-07-18
    • 1970-01-01
    相关资源
    最近更新 更多