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
Post a Comment