2015-09-09 6 views
1

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

код выглядит следующим образом:

#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

IIRC, вы передаете * копию * объектов, которые вы создаете, а не оригинальные. И копия имеет тип, определяемый переменной param. См. Http://www.cplusplus.com/forum/windows/9891/ – SJuan76

+2

Aaaand http://stackoverflow.com/questions/2432683/what-does-slicing-mean-in-c – SJuan76

+0

Нет элегантного способа исправить это без изменение вызова в 'main()'. Сожалею. –

ответ

2

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

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

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

1

В

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

[templated version] (http: //coliru.stacked-crooked. com/a/0e0b9b69598d3bc7) тоже не очень – sp2danny

+0

Мне очень приятно. Я очень впечатлен. Я не могу понять весь код, но я постараюсь понять. –

Смежные вопросы