c++ - Polymorphism and casting through struct with pointers -


full disclaimer first: have not compiled example code, nor real code (well, @ least deployed). still wrapping head around problem. in mind, have class structure:

a super base class use store instances base in same container , few "facet" classes use multiple inheritance encapsulate common behaviour.

class facet_a; class facet_b; class facet_c;  struct facet_converter {     facet_a * facet_a;     facet_b * facet_b;     facet_c * facet_c; };  class super_base {     public:      virtual ~super_base() {}     virtual facet_converter convert()=0;     virtual const facet_converter convert()const=0; //notice const...  };  class facet_a {     private:      int value_a;      public:      virtual ~facet_a() {}     facet_a():value_a(0) {}     void set_value_a(int v) {value_a=v;}     int get_value_a() const {return value_a;} };  class facet_b {     private:      float value_b;      public:      facet_b():value_b(0) {}     virtual ~facet_b() {}     void set_value_b(float v) {value_b=v;}     float get_value_b() const {return value_b;} };  class facet_c {     private:      char value_c;      public:      facet_c():value_c('a') {}     virtual ~facet_c() {}     void set_value_c(char v) {value_c=v;}     char get_value_c() const {return value_c;} }; 

all classes derive these always:

  • use super_base public base class, can store them in vector of these.
  • implement convert methods return facet_converter object pointers (shared, unique, raw, whatever) of derived class casted particular facet (null, if not applicable).
  • use facet_a, facet_b or facet_c base class depending on try implement.

the client code like...

std::vector<super_base *> v;  //fill super base stuff.  //let's use has integer!. for(auto sb : v) {     facet_converter fc=sb->convert();     if(fc.facet_a)     {         //do integer like... std::cout<<fc.facet_a->get_value_a()<<std::endl;     } }  //let's use has float. for(auto sb : v) {     facet_converter fc=sb->convert();     if(fc.facet_b)     {         //do float...     } }  //let's use has char. for(auto sb : v) {     facet_converter fc=sb->convert();     if(fc.facet_c)     {         //you drift...     } } 

horrible design apart (i've come point sick of visitors everywhere) particular example pretty barebones, trying do: casting down hierarchy without using dynamic_cast , "enforcing" compiler (it yell @ me if tried assignment non-base class in "convert" method).

so, of implemented class...

class derived_numeric:  //this 1 has float , and int     public super_base,     public facet_a,     public facet_b {     ///blah blah blah blah      virtual facet_converter convert()     {         facet_converter result;         result.facet_a=this;         result.facet_b=this;         result.facet_c=nullptr;     //assume no constructor struct initializes method, not case.         return result;     }      virtual const facet_converter convert()const     {         const facet_converter result;         result.facet_a=this;        //booom!!!. error, const derived_numeric can't caster facet_a because... it's const.         result.facet_b=this;         result.facet_c=nullptr;          return result;     } } 

and there's problem, right in const convert method. there's const , non const method because client code may work const , non const objects there's no way compiler gonna let me assign "const this" without const casting first.

considering i've come 2 solutions:

  • const_casting pointer in const method.
  • creating 2 facet_converter objects: facet_converter , facet_converter_const. they're same 1 has const pointers , other has regular pointers. let client code use 1 need.

both of them suffer horrible code repetition, since code same , few details change.

i've toyed idea of implementing const one, const_casting "this" pointer , lying method promises. want true constness?, add const modifier result of convert() , done it... seems easier, sneaky.

my question is, can implement idea without copying , pasting code , being sneaky?. remember need both const , non const (the derived object may change state using facets, or may not).

now, please consider not looking "your approach wrong" or "i don't know why want that". current situation want deal , learn about. know can use double dispatching or can bastardize whole base class contain every other possibility... looking alternatives it.

you make const facet_converter member of super_base , set via constructor.

class super_base { protected:     const facet_converter implementations;  public:     super_base( const facet_converter& implementations )         : implementations( implementations ) {};     virtual ~super_base() {};     const facet_converter& convert() const { return implementations; } }; 

when implement derived class, do:

derived_numeric::derived_numeric( ) : super_base( facet_converter( this, this, null ) ) 

you need add constructor struct call possible:

struct facet_converter {     facet_converter( facet_a* const& a, facet_b* const& b, facet_c* const& c )     {         facet_a = a;         facet_b = b;         facet_c = c;     }      facet_a * facet_a;     facet_b * facet_b;     facet_c * facet_c; }; 

i haven't tested using actual pointers , subclasses, might need tweaks.


Comments

Popular posts from this blog

yii2 - Yii 2 Running a Cron in the basic template -

asp.net - 'System.Web.HttpContext' does not contain a definition for 'GetOwinContext' Mystery -

mercurial graft feature, can it copy? -