繁体   English   中英

从子类调用父虚拟函数

[英]call parent virtual function from child class

我想用两个“单位”制作一些“决斗”。 我写了从两个“单元”构造的“决斗”类。 但是某种“单位”很特殊(从单位继承),例如英雄,老板等。他们想在战斗中使用特殊打击。 但是实际上“决斗”类并不知道谁是英雄,或者谁是纯粹的单位。

代码如下:

#include <iostream>

class unit{
  public:
   unit(){};
   virtual void make_hit(){
     std::cout<<"pure hit\n";
   }
};

class hero:public unit {
  public:
   hero():unit(){};
   void  make_hit(){
     std::cout<<"SUPER hit\n";
   }
};

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;

}

我有两个主要问题。

首先-我使用构造函数中的临时对象。 在Duel :: duel()完成时,该对象是非法的。

第二-我的英雄变成了纯粹的单位,并且不使用“超级成功”

是否可以用优雅的方式修复它(无需更改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();
}

还记得在基类中始终有一个虚拟析构函数。

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”类中。 该解决方案不是那么优雅,添加新类时需要更改“决斗”代码,这也有开销。

  ~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

我也尝试使用模板,但是找不到自动确定类型的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM