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?)
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.
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.
Related
C++. Imagine the following situation.
There's a class hierarchy of classes deriving from some base class A.
We cannot modify A because it is outside of our scope.
(Provided by a library, it is a MFC CView class, but that shouldn't matter here)
So there are A1, A2 etc which are different classes somehow derived from A and providing specific functionality.
Now imagine we define some new interface I to provide some new functionality.
Classes for concrete objects of the application will inherit from both one of the As and I.
Let's call them Bs. (There are again several of them, like B1 derived from A1 and I, B2 derived from A2 and I etc.)
Now it happens that to implement the interface of I, there is a lot of common code that needs functionality from A.
How can we organize the class hierarchy without repeating ourselves too much.
So for instance if there is a function I::f that needs to call A::f, for all derived classes Bn.
It seems like waste to re-implement I::f for every Bn.
But obviously, we cannot call A::f directly from I::f, as they aren't related.
I hope you get the point.
What is the pattern that can help us here?
The immediate solution to "call A::f from I::f without overhauling everything" would be dynamic_cast:
struct I {
void f() {
dynamic_cast<A *>(this)->f();
}
};
Note that this performs a full-fledged RTTI graph traversal to perform the cross-cast through the unknown Ax dynamic type of the object, so it might be on the slow side of things.
This is an attempt to understand the impact of using virtual base class inheritance, especially regarding runtime cost. The situation I have in mind also involves Interfaces (or ABC s for that).
I----------
/ | \ |
D1 D2 D3 Isub
| /
D3Dec
So, we have an Interface I and we have different implementations D1, D2, and D3. But now the twist is, there is a special decorator, which wraps just some (arbitrary) I implementation and then adds an extended feature based on the contract expressed through I.
Thus, from a logical or design viewangle, it would be desirable to express that extended ability through a sub-interface Isub derived from I. Thus any Isub automatically also fulfils the I contract.
Question: Performance impact
Now, to implement such in C++, any implementation of interface I must be done virtual, and likewise, Isub must inherit virtual from I, otherwise we'd end up with two I subobjects residing in D3Dec.
Does this mean, every implementation of I has to pay the price in terms of memory layout with tricky virtual base offset adjustments. Correct?
is the situation different when both I and Isub are pure virtual, i.e. have no members and only pure virtual functions? Would it then be possible to make that work without virtutal inheritance?
the tricky point to note is when client code only gets a reference to Isub. If clients call the extended functionality, they actually call into the implementation of said functionality within D3Dec, and this in turn uses the other I-functionality to implement the extended feature, since obviously D3dec does not know anything about the concrete I-implementation it decorates. Does this necessarily mean we have to use virtual inheritance? Or is there any template based trick to get around that but still have an (abstracted) sub-Interface Isub?
The obvious alternative is of course to cut the link between I and Isub, turning it into a trivial mix-in. This works, but is ugly, since Isub does not make much sense on its own, independent of I. Both even use the same data types on the signatures, etc...
You can avoid the diamond inheritance problem entirely by making the interface class a template parameter of the concrete class. Then there's no more need for virtual class inheritance.
class I { ... };
template<class Ifc>
class D3Impl : public Ifc
{ ... };
typedef D3Impl<I> D3;
class Isub : public I { ... };
class D3Dec : public D3Impl<Isub>
{ ... };
Consider a scenario(C++):
Class A, Class B, both derived from same parent class. For every instance of Class A, there is exactly one instance of Class B.
Class A keeps the pointer to Class B, such that instance of Class B is created in the Constructor of Class A.
Basically, in the implementation, Class A provides a way of accessing data from a file(XML). In fact, the methods in Class A in turn calls methods of Class B to retrieve or set value in the XML. For example, Class A has a getter function for retrieving tag value, after doing some operations at Class A level (mostly validations), Class A delegates to the getter function of Class B.
void GetXMLTagValue (const string& sTagName, string& sTagValue)
Question:
In a certain scenario, I got an instance of Class B alone. And I need to invoke a public non static method of Class A. Is there a recommended way of achieving this?
Well the easiest way would be just keep a pointer back to A. It'll be easy beacause A constructs B.
Nevertheless, it's worth questionning yourself about the design intention that's behind this special scenario.
You seem to implement the proxy design pattern, where A is the proxy (GUI ?) and B the real subject (persistent business object ?). The common base class is the interface of both the real object and its proxy. And A forwards the requests to B.
In principle the goal of the proxy is to provide a surrogate/placeholder to control access to the real object (Gang of 4). Your special scenario is a little bit different, as B forwards something to A:
What's the intent ?
must A be informed of some status changes of B ? In this case, I'd suggest to use the observer pattern and see the A function to be called as the (virtual) callback function. The advantage is that if you later come to the conclution that another object needs to be informed, it'll be easy to evolve.
does B take responsibilities that A doesn't have ? Should B manipulate A in a more extensive way ? Then you could see B as being a decorator. It works a little bit like a proxy. If you adopt the decorator approach, you could have other intermediary objects being plugged between the final client and B as between B and A. But seeing your one to one relationship and the fact that A creates B, this would be a more radical change in the design than adding observers; I'm not sure that it's what you're looking for in your design.
I was taught in class that in the case of single inheritance the VTBL includes all of the of the virtual functions the class can respond to. The following image should illustrate this.
In multiple inheritance I was taught that the VTBL includes all of the virtual functions that were first defined in that class or the ones which have been overriden in this class. This means that at run time you've got to search for the right method implementation using the dispatch algorithm.
I'm not entirely sure why this difference exists. Why couldn't the VTBL in the case of multiple inheritance consist of all the virtual functions that the class can respond to (just like in the case of single inheritance)? This should speed up the process since we don't have to look for the method implementation at run time throughout the whole inheritance hierarchy.
Can anyone clarify this for me?
Edit: When I refer to the dispatch algorithm for multiple inheritance I'm referring to the following:
Just to clarify: notice how we've got to traverse the hierarchy to search for the implementation rather than just going to the current class's VTBL and calling jumping to the method.
Here's a translated example from published German notes by Scott Meyers. Consider
class B1 {
public:
virtual void mf(); // may be overridden in derived classes
};
class B2 {
public:
virtual void mf(); // may be overridden in derived classes
};
class D: public B1, public B2 {};
void g(B2 *pb2)
{
pb2->mf(); // requires offset adjustment before calling mf?
}
The pointer argument being passed to g() needs an offset adjustment is needed only if D overrides mf and pb2 really points to a D. What should a compiler do? When generating code for the call,
It may not know that D exists. (that's the point of dynamic polymorphism: to be able to call future code without recompiling)
It can’t know whether pb2 points to a D (it only knows that only at runtime).
Because polymorphic classes need to remain flexible against the unbounded set of possible future further derivations, the problem is typically solved by
Creating special vtbls that handle offset adjustments.
For derived class objects, adding new vptrs to these vtbls, one
additional vptr for each base class after the first one.
Merging all the virtual functions into a single table would destroy that flexibility. Note that multiple "parallel" inheritance D: B1, B2 {}; is different from "stacked" inheritance D: M: B {};. The latter requires a single substitution chain, the former has two such chains and incompatible B1 and B2.
If you have to base class A and B of your multiply inherited object D, these have their own vtable layout and D needs to provide vtables which match the vtables of both A and B. Further, if another class derives from D and possibly from another similarly multiple inherited class, the same thing happens again, i.e., there are multiple vtables needed. They can't just simply be merged. As a result, multiply inherited objects typically have multiple vtables around and the compiler inserts code to first determine the function's correct vtable and then call it. I think the code determining the correct vtable based on a pointer to an object with multiple bases is just a simple addition or subtraction if the virtual function is not in a virtual base class and a look-up of the location of the virtual base class otherwise, i.e., there isn't anything really expensive being done but more than just an indirect call is needed.
I am after your opinion on how best to implement an inheritance pattern in C++. I have two base classes, say
class fooBase{
protected:
barBase* b;
};
class barBase{};
where fooBase has a barBase. I intend to put these classes in a library, so that wherever I have a fooBase it can use its barBase member.
I now intend to create a specialisation of these in a specific program
class fooSpec : public fooBase{};
class barSpec : public barBase{};
Now I want fooSpec::b to point to a barSpec instead of a barBase. I know that I can just initialise b with a new barSpec, but this would require me to cast the pointer to a barSpec whenever I wanted to use specific functions in the specialisation wouldn't it?
Is there another way that this is often acheived?
Cheers.
Create a method in your specclass to cast the b into the special version.
That way instead of casting it all the time, it looks like a getter.
On the other hand OO is about programming towards interfaces and not objects. So what you are doing here looks like programming towards objects. But the is difficult to see as this example is purely theoretical.
You may consider the template solution:
template <class T>
class fooBase{
protected:
T* b;
};
and then use it as
class fooSpec : public fooBase<barSpec>{};
while ordinarily, the base would be used as fooBase<barBase>.
Is this what you want?
Normally we create a function that has the cast and returns the pointer -- and use that instead of the member directly.
Now I want fooSpec::b to point to a barSpec instead of a barBase.
There's no such thing as fooSpec::b. b belongs to fooBase, and your new class fooSpec is a (specialization of) a fooBase. You can't change the fact that b, a fooBase member, is of type barBase. This is a property of all the instances of fooBase that you can't invalidate in the particular subset of instances concerned by your specialization.
I know that I can just initialise b with a new barSpec, but this would
require me to cast the pointer to a barSpec whenever I wanted to use
specific functions in the specialisation wouldn't it?
Yes and no. Yes, you need to do that cast; but no, you don't need to do it every time. You can encapsulated in a function of fooSpec.
Is there another way that this is often acheived?
Not that I'm aware of.
this would require me to cast the pointer to a barSpec whenever I wanted to use specific functions in the specialisation wouldn't it?
That depends on whether the method you are trying to invoke is defined in the superclass and whether it is virtual.
You need to cast the pointer before invoking a method if one of the following is true...
The method belongs to the subclass only
The superclass has an implementation of the method and the subclass's implementation does not override the implementation in the superclass. This amounts to a question of whether the function is a virtual function.
Avoid data members in non-leaf classes, use pure virtual getters instead. If you follow this simple rule, your problem solves itself automatically.
This also makes most non-leaf classes automatically abstract, which may seem like an undue burden at first, but you get used to it and eventually realize it's a Good Thing.
Like most rules, this one is not absolute and needs to be broken now and then, but in general it's a good rule to follow. Give it a try.
If it looks too extreme, you may try one of the design patterns that deal with dual hierarchies such as Stairway to Heaven.