c++ - Is dynamic_casting through inheritance hierarchy bad practice? -


i have got following data structure:

class element {   std::string gettype();   std::string getid();   virtual std::vector<element*> getchildren(); }  class : public element {   void adda(const *a);   void addb(const b *b);   void addc(const c *c);   std::vector<element*> getchildren(); }  class b : public element {   void addb(const b *b);   void addc(const c *c);   std::vector<element*> getchildren(); }  class c : public element {   int someactualvalue; }  /* classes have kind of container store pointers ,  * child elements. let's keep code short. */ 

the data structure used pruduce acyclic directed graph. c class acts "leaf" containing actual data algebra-tasks. , b hold other information, names, types, rules, favourite color , weather forecast.

i want program feature, window pops , can navigate through existing structure. on way want show path user took pretty flow chart, clickable go in hierarchy. based on visited graph-node (which either a, b or c) information has computed , displayed.

i thought make std::vector of type element* , use last item active element work with. thought pretty nice approach, makes use of inheritance there , keeps code need quite small.

but have lot of situations these:

element* currentelement;  void addtocurrentelement(const c *c) {   if(a *a = dynamic_cast<a*>(currentelement)) {     //dosomething, if not, check if currentelement b   }     } 

or worse:

vector<c*> filterforc's(a* parent) {   vector<element*> elevec = parent.getchildren();   vector<c*> retvec;   for(element* e : elevec) {     if (e.gettype() == "class c") {       c *c = dynamic_cast<c*>(e);       retvec.append(c);     }   } } 

it object oriented. use inheritance. feels threw comfort oop gives me on board , decided use raw pointers , bitshifts again. googling subject, found lot of people saying casting up/down bad design or bad practice. totally believe true, want know why exactly. can not change of code part of bigger project, want know how counter situation when design program in future.

my questions:

  1. why casting up/down considered bad design, besides fact looks horrible?
  2. is dynamic_cast slow?
  3. are there rules of thumb how can avoid design 1 explained above?

there lot of questions on dynamic_cast here on so. read few , don't use method in own code, answer reflects opinion on subject rather experience. watch out.

(1.) why casting up/down considered bad design, besides fact looks horrible?

(3.) there rules of thumb how can avoid design 1 explained above?

when reading stroustrup c++ faq, imo there 1 central message: don't trust people never use tool. rather, use right tool task @ hand.

sometimes, however, 2 different tools can have similar purpose, , here. can recode functionality using dynamic_cast through virtual functions.

so when dynamic_cast right tool? (see what proper use case dynamic_cast?)

  • one possible situation when have base class can't extend, nevertheless need write overloaded-like code. dynamic-casting can non-invasive.

  • another 1 want keep interface, i.e. pure virtual base class, , don't want implement corresponding virtual function in derived class.

often, however, rather want rely on virtual function -- if reduced uglyness. further it's more safe: dynamic-cast can fail , terminate program, virtual function call (usually) won't.

moreover, implemented in terms of pure functions, not forget update in required places when add new derived class. on other hand, dynamic-cast can forgotten in code.

virtual function version of example

here example again:

element* currentelement;  void addtocurrentelement(const c *c) {   if(a *a = dynamic_cast<a*>(currentelement)) {     //dosomething, if not, check if currentelement b   }     } 

to rewrite it, in base add (possibly pure) virtual functions add(a*), add(b*) , add(c*) overload in derived classes.

struct : public element {      virtual add(a* c) { /* */ }      virtual add(b* c) { /* b */ }      virtual add(c* c) { /* c */ } }; //same b, c, ... 

and call in function or possibly write more concise function template

template<typename t> void addtocurrentelement(t const* t) {     currentelement->add(t); } 

i'd standard approach. mentioned, drawback pure virtual functions require n*n overloads maybe n might enough (say, if a::add requires special treatment).

other alternatives might use rtti, crtp pattern, type erasure, , possibly more.


(2.) dynamic_cast slow?

when considering majority of answers throughout net state, yes, dynamic cast seems slow, see here example. yet, don't have practical experience support or disconfirm statement.


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -