从子类调用父类虚函数

call parent virtual function from child class

本文关键字:函数 父类 调用 子类      更新时间:2023-10-16

我想用两个"单位"做一些"决斗"。我写由两个"单位"构成的"决斗"类。但有些"单位"是特殊的(继承自单位),如英雄、boss等。他们想在战斗中使用特殊打击。但实际上职业"决斗"并不知道谁是英雄,谁是纯单位。

代码如下:

#include <iostream>
class unit{
  public:
   unit(){};
   virtual void make_hit(){
     std::cout<<"pure hitn";
   }
};
class hero:public unit {
  public:
   hero():unit(){};
   void  make_hit(){
     std::cout<<"SUPER hitn";
   }
};
class duel {
  unit *a, *b;
  public:
  duel(unit _a, unit _b):a(&_a),b(&_b){};
  void start (){
    a->make_hit();
    b->make_hit();
  }
};
int main(){
  duel(unit(),hero()).start();
  return 0;
}

我有两个主要问题。

首先-我使用在构造函数中引用临时对象。当决斗::决斗()结束时,对象是非法的。

秒-我的英雄变成了纯单位,并且不使用"SUPER hit"

是否有可能以优雅的方式修复它(不改变main()中的调用)?

由于切片,最好总是将多态性与智能指针。这是一种可能的设计:

#include <iostream>
#include <memory>
#include <utility>
using namespace std;
class unit_base
{
public:
    virtual ~unit_base() = default;
    virtual void make_hit() =0;
};
class unit : public unit_base
{
public:
    unit() = default;
    virtual void make_hit() override
    {
        cout << "pure hit" << endl;
    }
};
class hero : public unit_base
{
public:
    hero() = default;
    virtual void make_hit() override
    {
        cout << "SUPER hit" << endl;
    }
};
class duel
{
public:
    duel( shared_ptr<unit_base> a, shared_ptr<unit_base> b )
        : a(a), b(b)
    {}
    void start()
    {
        auto aa = a.lock();
        auto bb = b.lock();
        if( aa && bb )
        {
            aa->make_hit();
            bb->make_hit();
        } else {
            cout << "duelist expired" << endl;
        }
    }
private:
    weak_ptr<unit_base> a, b;
};
int main()
{
    // use with temporarys
    duel{ make_shared<unit>(), make_shared<hero>() }.start();
    cout << "-------------" << endl;
    // use with variables
    auto u = make_shared<unit>();
    auto h = make_shared<hero>();
    duel d{h,u};
    d.start();
    cout << "-------------" << endl;
    // try to use with expired duelists
    u.reset();
    d.start();
}

还要记住在基类中总是有一个虚析构函数

In

duel(unit _a, unit _b):a(&_a),b(&_b){};

在按值传递时对对象进行切片。要解决这个问题,可以在构造函数

中引入指针。
duel(unit* _a, unit* _b):a(_a),b(_b){};

然后你需要改变main()来创建对象并将它们传递给duel

int main(){
    unit npc;
    hero bob;
    duel d(&npc,&bob);
    d.start();
    return 0;
}

我在c++中找到的唯一方法是在"决斗"类中构造函数的所有组合。这个解决方案不是那么优雅,需要在添加新类时修改"决斗"代码,而且这也有开销。

  ~duel(){
    delete a;
    delete b;
  }
#define _cc(t1, t2) duel(t1 _a, t2 _b) : a(new t1 (_a)), b (new t2(_b)){}
  _cc(unit,unit);
  _cc(hero,unit);
  _cc(unit,hero);
  _cc(hero,hero);
#undef _cc

我也试过使用模板,但我找不到一种方法,使自动类型确定