вызовите родительскую виртуальную функцию из дочернего класса

Я хочу сделать несколько «дуэлей» с двумя «единицами».
Я пишу класс «дуэль», который состоит из двух «единиц».
Но какой-то «юнит» особенный (унаследованный от юнитов), такой как герои, боссы и т. Д. И они хотят использовать специальные удары во время битвы.
Но на самом деле класс «дуэль» не знает, кто герой, а кто чистый юнит.

Код выглядит так:

#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())?

1

Решение

Из-за нарезки лучше всегда использовать полиморфизм вместе с
смарт-указатели. Это был бы возможный дизайн:

#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();
}

Также помните, что в вашем базовом классе всегда должен быть виртуальный деструктор.

2

Другие решения

В

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;
}
1

Единственный способ, который я нашел для себя в 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

Я также попытался использовать шаблон для этого, но я не могу найти способ сделать автоматическое определение типа.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector