c++ - Creating derived class instance using base class instance -
i have base class instance, there derived class inherits base class, want transform base instance derived instance, (if possible without copying (maybe sending derived class reference of base class)) how can achieve that?
note: need because i'm using factory design pattern identify derived class needed created using parameter located in base instance.
//class //class b: public (pure virtual) //class c: public b b bfactory::makeb(a &a) { int n=a.getn(); if(n==1){ return new c(); } }
thanks.
consider case of car.
you can treat lamborghini car.
you can treat yugo car.
you can treat car lamborghini if lamborghini. in c++ means pointer car points lamborghini. in order lamborghini pointer out of car pointer should use dynamic_cast. if car not point lamborghini, dynamic_cast return null. keeps trying pass off yugo lamborghini , blowing yugo's engine.
but when lamborghini being treated car, can car things. if copy lamborghini car, strip out lamborghini-ness forever. it's gone.
code time!
this, i'm afraid cannot done:
//class //class b: public (pure virtual) //class c: public b b bfactory::makeb(a &a) { int n=a.getn(); if(n==1){ return new c(); } }
c being copied b , b being returned. b need constructor took c, point moot. b cannot instantiated if it's pure virtual. we'll ignore leak new c()
also can't use reference job, pretty same problem, you're trapped returning pointer
b * bfactory::makeb(a &a) { int n=a.getn(); if(n==1){ return new c(); } }
now i'm going make suggestion: build make function b , handle case doesn't map recognized b.
class b: public { public: virtual ~b(){} static b * makeb(a & a) { switch(a.getn()) { case 1: return new c(); } return null; } };
but leads recommendation: why should b know anything? , point of @ level? why storing build codes classes 2 or more steps down hierarchy? bad maintenance point of view. point of objects know , how manipulate themselves. short-circuiting leads pain.
class b: public { public: virtual ~b(){} virtual b* makeb() = 0; };
now b makes bs, needs no a, , extend b stuck figuring out how make themselves--a task should know better else. safer because there never possibility of code unrecognised b new class.
class c: public b { public: b* makeb() { return new c(); } }; class d: public b { public: b* makeb() { return new d(); } };
edit: traditional factory
you're asking abstract factory. need nothing. don't need class. don't need class a. goal of sort of factory caller knows nothing class. providing a, caller needs know how make or have factory makes a.
first bit of set-up in header file bfactory.h:
#ifndef bfactory_h_ #define bfactory_h_ #include <exception> class b { public: virtual ~b(){} virtual std::string whatami() = 0; protected: // data members common b subclasses }; enum btype { gimmie_a_c, gimmie_a_d, gimmie_an_e }; class badtypeexception: public std::exception { public: const char* what() const noexcept { return "dude! wtf?!?"; } }; b* bfactory(enum btype type); #endif /* bfactory_h_ */
here i'm going deviate book way little. rather using integer identify type built, i'm going use enum. 2 reasons: easier read , understand gimme_a_c 1 , generates compiler error if try provide value not enumerated.
enum btype { gimmie_a_c, gimmie_a_d, gimmie_an_e };
and exception flag stupidity if enum updated new types (gimmie_an_e) factory not.
class badtypeexception: public std::exception { public: const char* what() const noexcept { return "dude! wtf?!?"; } };
this factory client needs see. don't see c. don't see d. have no clue c , d exist in way other names listed in enum btype
. ever see pointers b.
now implementation bfactory.cpp:
#include "bfactory.h" class c:public b { std::string whatami() { return "c"; } }; class d:public b { std::string whatami() { return "d"; } }; b* bfactory(enum btype type) { switch(type) { case gimmie_a_c: return new c(); case gimmie_a_d: return new c(); default: throw badtypeexception(); } }
i'll leave reader spot stupid bug in above code makes these error prone , why don't them.
and usage, main.cpp:
#include "bfactory.h" int main() { b * temp; temp = bfactory(gimmie_a_c); std::cout << temp->whatami() << std::endl; delete temp; temp = bfactory(gimmie_a_d); std::cout << temp->whatami() << std::endl; delete temp; //temp = bfactory(1001); // won't compile try { temp = bfactory(gimmie_an_e); // compile, throws exception std::cout << temp->whatami() << std::endl; } catch(badtypeexception& wtf) { std::cerr << wtf.what() << std::endl; } }
there still absolutely no use or involvement of a. if exists, should no nothing b or children of b.
these days there little improvement can make pointers little safer. unique_ptr allows maintain polymporphic advantages of pointer b without memory management woes.
std::unique_ptr<b> bfactory(enum btype type) { switch(type) { case gimmie_a_c: return std::unique_ptr<b>(new c()); case gimmie_a_d: return std::unique_ptr<b>(new d()); default: throw badtypeexception(); } }
and new main:
int main() { std::unique_ptr<b> temp; temp = bfactory(gimmie_a_c); std::cout << temp->whatami() << std::endl; temp = bfactory(gimmie_a_d); std::cout << temp->whatami() << std::endl; }
Comments
Post a Comment