如何从基类中的派生类调用函数

How to call a function from a derived class in a base class?

本文关键字:派生 调用 函数 基类      更新时间:2023-10-16

我花了几个小时在网上寻找,但没有一个人遇到和我一样的问题。基本上,我有一个名为MainShop的基类,它有3个派生类,分别是SwordShop,SpellBookShop和BowShop。我希望基类能够从派生类之一调用函数,但无论我做什么,它似乎都不起作用!这是我的代码:

#include "MainShop.h"
//BaseClass cpp
void MainShop::EnterShop(Hero& hero)
{
    //Display Choices
        switch (choice)
        {
            //Swords
            case 1: SwordShop::soldierShop(hero);//DOES NOT WORK!!
                        break;
            case 2: SpellBookShop::MageShop(hero);//Staffs
                        break;
            case 3: BowShop::ArcherShop(hero);//Bows
                        break;
            default: cout << "Error!, Please try again.";
                        MainShop::EnterShop(hero);

        }
}

我还有另外两个派生类,但它的概念基本相同。我在其中一个派生类中有一个函数,我想从基类调用它。这是我的一个派生类:

//SwordShop derived cpp
#include "SwordShop.h"
void SwordShop::soldierShop(Hero& hero)
{
  /* some code here*/
}

在超类方法中选择特定的子类实例不是一个好的设计 ,例如,由于运行时开销和未来的维护等,通过dynamic_cast

您可以将这种开关案例逻辑的负担卸载到虚函数上,这些函数由语言设计,通过基类指针/引用调用特定实例。

例如:

class MainShop
{
public:
   virtual void EnterShop(Hero &hero) = 0;
};
class SwordShop: public MainShop
{
   void EnterShop(Hero &hero)
   {
      soldierShop(hero);
   }
};
class SpellBookShop: public MainShop
{
   void EnterShop(Hero &hero)
   {
      MageShop(hero);
   }
};
int main()
{
   ...
   MainShop *shop = new SwordShop;
   // calling soldierShop
   shop->EnterShop(hero);
   ..
   shop = new SpellBookShop;
   // calling MageShop
   shop->EnterShop(hero);
   ...
}
我想

你可以尝试这样的事情:

Derived* derived = dynamic_cast<Derived*>(this);
if (derived) {
    // this is of Derived type
} else {
    // this is of base type but not Derived
}

尽管正如建议的那样,您最好使用虚拟函数,因为它是正确的用例:

class Base {
public:
    virtual void someMethod() = 0;
    void anotherMethods() {
        someMethod(); // determined by implementation in derived class
    }
};
class Derived1 : public Base {
    virtual void someMethod() override {
        // body
    }
};
class Derived2 : public Base {
    virtual void someMethod() override {
        // body
    }
};

更好的可读性,更少的错误,更理智。

如果您需要从任何商店对象(SwordShop等)调用EnterShop,那么覆盖基类中的虚拟函数是可行的方法。

class MainShop
{
     ...
     virtual void process_hero(Hero& hero)
     {
          // add default implementation or set as pure virtual
     }
     ...
};
void MainShop::EnterShop(Hero& hero)
{
    process_hero(hero);
}
class SwordShop: public MainShop
{
public:
    void process_hero(hero)
    {
        soldierShop(hero);
    }
};
...

但是,在我看来,您希望管理器对象根据"选择"变量调用函数。如果是这种情况,请使用组合而不是继承。

更喜欢组合而不是继承?

这样的事情怎么样?显然,您必须实现.shop()函数:

MainShop *ms;
switch(input){
    case 1:
    ms = new soldierShop(); break;
    case 2:
    ms = new MageShop(); break
    case 3:
    ms = new ArcherShop(); break;
}
ms.shop();

通常有 2 个选项可用于实现所需的功能:

  1. 使用 dynamic_cast<> 将指针提升this指向所需的派生类型,并在强制转换成功时调用所需的任何内容。
  2. 将模板化基类与奇怪的重复出现的模板模式结合使用 - 基本上,将所需的派生类型作为模板参数传递给基类 (http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。