c++ - Copying object from a superclass pointer -


suppose have 2 classes base class , inherited class follows:

class magic : public attack { public:     magic(int uid, std::string &name) : attack(actiontype::magicaction, uid, name)     {      } };  class macromagic : public magic {     macromagic(int uid) : magic(uid, std::string("testing"))     {     }     void preuse() override     {         std::cout << "test" << std::endl;     } } 

i have shared_ptr instance of magic copy, @ runtime not know whether pointer points instance of magic, macromagic or may have inherited magic. want able copy object pointed shared_ptr so:

battles::magic_ptr mgptr = magicnamemap[name];             if (mgptr.get() != nullptr)             {                 return magic_ptr(new magic(*mgptr));             }             return mgptr; 

where magic_ptr typedef shared_ptr around magic class. specifying virtual copy function , calling that, i'd make less obtuse , easier maintain. assume can copy constructor, i'm unsure how in instance. way have now, pointer returned above code not call override preuse() function.

a bit of guidance appreciated, thanks

i specifying virtual copy function , calling that, i'd make less obtuse , easier maintain.

you're working against language.

you accomplish after, don't recommend it, , not easier setup or maintain virtual magic* clone() = 0.

perhaps outline problem brought conclusion, , can there. there alternatives don't fight language.

edit

here's way around using external function table (t_magic_operation_table). can apply , create several function tables , keep them around. since exist in magic object single pointer, can make these tables quite large (if needed). if magic types can use same data/members, 1 approach. careful: threw suuuper-fast. demonstrates technique, it's pretty bad otherwise:

#include <iostream> #include <string>  namespace monspiel {  inline unsigned prndm(const unsigned& max) {     return 1 + arc4random() % max; }  class t_ghoul; class t_biclops;  class t_magic;  class t_hero {     t_hero();     t_hero(const t_hero&);     t_hero& operator=(const t_hero&); public:     t_hero(const std::string& inname) : d_name(inname) {     }      const std::string& name() const {         return this->d_name;     }      template<typename tenemy, typename tmagic>     void attack(tenemy& enemy, tmagic& magic) const {         if (enemy.isdead()) {             return;         }          enemy.hit(magic.power());          if (enemy.isdead()) {             std::cout << this->name() << ": see in prequel...\n\n";         }         else {             std::cout << this->name() << ": have had enough " << magic.name() << ", " << enemy.name() << "???\n\n";         }     }      /* ... */ private:     const std::string d_name; };  class t_enemy {     t_enemy();     t_enemy(const t_enemy&);     t_enemy& operator=(const t_enemy&); public:     t_enemy(const std::string& inname) : d_name(inname), d_lifepoints(1000) {     }      virtual ~t_enemy() {     }      const std::string& name() const {         return this->d_name;     }      bool isdead() const {         return 0 >= this->d_lifepoints;     }      const int& lifepoints() const {         return this->d_lifepoints;     }      void hit(const int& points) {         this->d_lifepoints -= points;     }      /* ... */ private:     const std::string d_name;     int d_lifepoints; };  class t_ghoul : public t_enemy { public:     static int maxdaysawake() {         return 100;     }      t_ghoul(const std::string& inname) : t_enemy(inname), d_bouyancy(prndm(100)), d_proximitytozebra(prndm(100)), d_daysawake(prndm(maxdaysawake())) {     }      const int& bouyancy() const {         return this->d_bouyancy;     }      const int& proximitytozebra() const {         return this->d_proximitytozebra;     }      const int& daysawake() const {         return this->d_daysawake;     }  private:     int d_bouyancy;     int d_proximitytozebra;     int d_daysawake; };  class t_biclops : public t_enemy { public:     t_biclops(const std::string& inname) : t_enemy(inname), d_istethered(prndm(2)), d_amountofsunblockapplied(prndm(100)) {     }      const bool& istethered() const {         return this->d_istethered;     }      const int& amountofsunblockapplied() const {         return this->d_amountofsunblockapplied;     }  private:     bool d_istethered;     int d_amountofsunblockapplied; };  class t_magic_operation_table { public:     typedef void (*t_ghoul_skirmish_function)(t_magic&, t_ghoul&);     typedef void (*t_biclops_skirmish_function)(t_magic&, t_biclops&);      t_magic_operation_table(t_ghoul_skirmish_function ghoulattack, t_biclops_skirmish_function biclopsattack) : d_ghoulattack(ghoulattack), d_biclopsattack(biclopsattack) {     }      void willskirmish(t_magic& magic, t_ghoul& ghoul) const {         this->d_ghoulattack(magic, ghoul);     }      void willskirmish(t_magic& magic, t_biclops& biclops) const {         this->d_biclopsattack(magic, biclops);     }  private:     t_ghoul_skirmish_function d_ghoulattack;     t_biclops_skirmish_function d_biclopsattack; };  class t_action { public:     typedef enum t_type {         noaction = 0,         magicaction,         clubaction,         classaction     } t_type; };  class t_attack { public:     t_attack(const t_action::t_type& actiontype, const int& uid, const std::string& inname) : d_actiontype(actiontype), d_uid(uid), d_name(inname) {     }      virtual ~t_attack() {     }      void reset() {         /* ... */     }      const std::string& name() const {         return this->d_name;     }  private:     t_action::t_type d_actiontype;     int d_uid;     std::string d_name; };  class t_magic : public t_attack {     t_magic();     t_magic(const t_magic&);     t_magic& operator=(const t_magic&);      static void ghoulskirmisha(t_magic& magic, t_ghoul& ghoul) {         magic.d_accuracy = ghoul.bouyancy() + prndm(16);         magic.d_power = ghoul.proximitytozebra() + prndm(43);     }      static void ghoulskirmishb(t_magic& magic, t_ghoul& ghoul) {         magic.d_accuracy = ghoul.bouyancy() / magic.flammability() + prndm(32);         magic.d_power = t_ghoul::maxdaysawake() - ghoul.daysawake() + prndm(23);     }      static void biclopsskirmisha(t_magic& magic, t_biclops& biclops) {         if (biclops.istethered()) {             magic.d_accuracy = 90 + prndm(16);         }         else {             magic.d_accuracy = 40 + prndm(11);         }          magic.d_power = biclops.amountofsunblockapplied() + prndm(17);     }      static void biclopsskirmishb(t_magic& magic, t_biclops& biclops) {         if (biclops.istethered()) {             magic.d_accuracy = 80 + prndm(80);         }         else {             magic.d_accuracy = 50 + prndm(50);         }          magic.d_power = 80 + prndm(30);     }      const t_magic_operation_table* nextoperationtable() {         static const t_magic_operation_table tables[4] = {             t_magic_operation_table(ghoulskirmisha, biclopsskirmisha),             t_magic_operation_table(ghoulskirmishb, biclopsskirmishb),             t_magic_operation_table(ghoulskirmishb, biclopsskirmisha),             t_magic_operation_table(ghoulskirmisha, biclopsskirmishb)         };          return & tables[arc4random() % 4];     }  public:     t_magic(const int& uid, const std::string& inname) : t_attack(t_action::magicaction, uid, inname), d_power(-1), d_accuracy(-1), d_operationtable(0) {     }      int flammability() const {         return prndm(73);     }      int power() const {         return this->d_power;     }      void reset() {         t_attack::reset();         this->d_power = -1;         this->d_accuracy = -1;         this->d_operationtable = 0;     }  private:     /* assigns this->d_operationtable */     void updateoperationtableforattack() {         this->d_operationtable = nextoperationtable();     }  public:     void herowillattack(const t_hero& hero, t_ghoul& ghoul) {         this->updateoperationtableforattack();         this->d_operationtable->willskirmish(*this, ghoul);         std::cout << hero.name() << " vs. " << ghoul.name() << "(lp:" << ghoul.lifepoints() << ")";         this->printstate();     }      void herowillattack(const t_hero& hero, t_biclops& biclops) {         this->updateoperationtableforattack();         this->d_operationtable->willskirmish(*this, biclops);         std::cout << hero.name() << " vs. " << biclops.name() << "(lp:" << biclops.lifepoints() << ")";         this->printstate();     }      void printstate() {         std::cout << ": magic { power: " << this->d_power << ", accuracy: " << this->d_accuracy << ", operation table: " << this->d_operationtable << "}\n";     }  private:     int d_power;     int d_accuracy;     const t_magic_operation_table* d_operationtable; };  template<typename tenemy> void attackenemywithmagic(t_hero& hero, tenemy& enemy, t_magic& magic) {     if (!enemy.isdead()) {         magic.herowillattack(hero, enemy);         hero.attack(enemy, magic);         magic.reset();     } }  inline void playit() {      t_hero zoe("zoe");     t_hero aragosta("aragosta");      t_ghoul ghoul0("al paca");     t_ghoul ghoul1("spud");     t_ghoul ghoul2("sleepy");      t_biclops biclops("scimpanzè");      t_magic hemlock(59, "hemlock");     t_magic babypowder(91, "baby powder");      (size_t idx(0); idx < 1000; ++idx) {         attackenemywithmagic(zoe, ghoul1, hemlock);         attackenemywithmagic(aragosta, biclops, babypowder);         attackenemywithmagic(zoe, ghoul2, hemlock);         attackenemywithmagic(aragosta, ghoul0, babypowder);     } } } /* << monspiel */  int main(int argc, char* const argv[]) { #pragma unused(argc) #pragma unused(argv)     monspiel::playit();     return 0; } 

another option create stores (e.g. vector), each different magic type. fill vector point objects in stores. way, can create 1 contiguous allocation each type , randomize , weigh needed. useful if magic objects' sizes vary considerably.


Comments