1

Consider I have series of derived classes for example as listed below:

class A
{
...
}

class B1 : public A //there may be many B's here say, B2, B3 etc
{
 ...
}
class C1 : public B1 //may be more C's as well
{
...
}

I would like to put all of the objects in single container, thus all would be of type class A.

Suppose I would like to add a function to class C1, what would be the best way to achieve this? My options would be introducing it in the base class A and write the needed implementation in C1, or, I could introduce it in C1 and do dynamic casting to access it. Which one is preferred? Is dynamic casting too expensive? (My main constrain is the run time.I have a flag in the base class to indicate what type of derived object it is, thus I do not have to dynamic cast every object in the container. Does adding unnecessary functions to base class can result in bad instruction cache use?)

user6386155
  • 825
  • 7
  • 17
  • 4
    No one can tell you if dynamic casting is "too expensive" because what you can afford is subjective. As that appears to be what you're after ("My main constrain is the run time") I would recommend doing it both ways and benchmarking the results to see if it is too expensive for your particular hardware and compiler optimizations and use cases and external restrictions and... – Altainia Aug 29 '16 at 17:38
  • 2
    Making an interface too broad is bad design and so is downcasting, you might one to keep an additional collection with pointers to more specific interfaces. – imreal Aug 29 '16 at 17:38
  • You could use a `variant` with a visitor pattern. – AndyG Aug 29 '16 at 17:40
  • You shouldn't be storing your derived objects in a literal `container` because that will cause slicing. – kfsone Aug 29 '16 at 18:27
  • just btw if you know the type you are casting, you don't really need to use dynamic cast, but rather something like `boost::polymorphic_downcast`. – Jaa-c Aug 29 '16 at 18:54
  • @imreal, I agree with you regarding keeping multiple collections, however that does not seem to be a natural choice for the problem I am working on – user6386155 Aug 29 '16 at 19:35

2 Answers2

2

You don't tell us the purpose of the new function in C1, and this does affect the answer, but as rough guidelines:

  • If the new function is a general behavior that you may need on any object and C1 happens to be the first user, definitely just add the interface to A.
  • If the new function is specific to the C series of classes but it can follow some general pattern (for example post-processing), add a post_process method to A, override it in C1, and have that method call private implementation methods of C1 to do the actual specific post-processing task.
  • If neither of these are the case you may wish to reconsider your use of inheritance as it's possible you're using it to represent a relationship other than substitution.
Mark B
  • 95,107
  • 10
  • 109
  • 188
  • The new function can only be performed in `C1` due to the type of the private data it has access to and it is called not so frequently. – user6386155 Aug 29 '16 at 19:39
0

adding a virtual function to your base class A is better because:

  • you should avoid dynamic cast especially in performance sensitive code. Please see Performance of dynamic_cast?

  • you should avoid having conditions to examine the object type (e.g. is it A, B1, or C1 ?) before performing a type-specific operation. Not only because it's slow, but also because if you do so, every time you add a new object type (e.g. C2) you will need to check all those conditions to see if they need to be updated.

Community
  • 1
  • 1
HazemGomaa
  • 1,620
  • 2
  • 14
  • 21