Cost of virtual inheritance from an interface - c++

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>
{ ... };

Related

How to represent C++ private inheritance in an UML diagram?

In C++, one can create a sub-class via public, protected, or private inheritance. What's the notation to indicate that in a UML class diagram? I'm thinking about putting a label on the arrow but not sure if that's common practice.
What is private inheritance in C++?
Private inheritance in C++, such as:
class B1 {
public:
void test();
...
};
class D1 : private B1 {
public:
void demo() { test(); }
...
};
means that every instance of D1 is an instance of B1, but that is hidden for the outside world. This strange construct aims at implementing the derived class by reusing the code of the base class, but as if there would be no inheritance.
In consequence, unlike public inheritance, a D1 object could not be used where a B1 object is expected:
B1 *p = new D1; //ouch -> error: ‘B1’ is an inaccessible base of ‘D1’
Is this UML inheritance?
In UML, when a derived class specializes a more general base classe, it means the following:
Type conformance means that if one Type conforms to another, then any instance of the first Type may be used as the value of a TypedElement whose type is declared to be the second Type. A Classifier is a Type, and conforms to itself and to all of its generalizations.
So in UML, if D1 specialises (i.e. inherits from) B1, a D1 instance could always be be used in place of a B1 object. This does not match the C++ private inheritance.
Moreover, there is not either a realization relationship between an interface and its implementations either, since D1 does not conform to the interface defined by B1:
An InterfaceRealization relationship between a BehavioredClassifier and an Interface implies that the BehavioredClassifier conforms to the contract specified by the Interface by supporting the set of Features owned by the Interface, and any of its parent Interfaces.
How to represent it in standard UML?
Obviously, there is a dependency: D1 depends on B1. So you could simply show a dependency. But this does not really help to grasp the kind of relationship and is not very useful. (unless you add a comment to explain)
A better approach would therefore be to map UML to match the C++ semantics. In this regard, you could envisage to model the private inheritance as a composition relation:
Why? Because the situation is very similar (although not completely) to the following composition alternative:
class B2 {
public:
void test();
...
};
class D2 {
private:
B2 base; // instead of private inheritance
public:
void demo() { base.test(); } // base members accessed via base
...
};
So all we do in the UML model here, is to make explicit that in any D1 instance, there is a B1 sub-object not accessible directly from the outside world.
Edit: Other alternatives?
In the former and now obsolete UML 1.4, a generalization relationship could have a stereotype «Implementation» that would have fulfilled your need, but is no longer supported since 2005, and might mislead some readers who associate "implementation" with interface:
Specifies that the child inherits the implementation of the parent (its attributes, operations and methods) but does not make public the supplier's interface, nor guarantee to suport them, thereby violating substituability. This is private inheritance and is usually used only for programming implementation puproposes.
Digging a little bit in the UML metamodel, it appears that generalization has a isSubstitutable property which is true by default. So you could think of using your own language-specific profile, and define therein a stereotypes «Private inheritance» and «Protected inheritance» for a specialization of the Generalization metamodel element, both with isSubstituable=false. This would allow:
This could be a very pragmatic and readable way to convey your language-specific design intent, including that a D1 object is not substituable for B1. But be aware that this is not without risks: isSubsituable is only about run time promises, and has in reality no impact regarding inheritance rules of public features in UML. Automated tools might therefore come to a different conclusion than your readers (this is why I proposed another approach above).
I would say with UML it's usually the type of relationship it has for example one to one or one to many. If you are deriving from an abstract class, interface or just another base class. Usually during inheritance you would use the protected keyword so that everything is private to any class outside of inheritance.
After inheriting from a base class you can also override methods from the base class as well as run the base method from inside the overridden method.
I believe what you are looking for here is the protected keyword which basically is private inheritance. Only related classes have the ability to access such members. For example, you create a base class with protected members and then use these members in inherited classes or classes that derive from the base.
Here is more info
https://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm

Class with mix of pure virtual and virtual methods

I created an abstract class which has a set of pure virtual methods only. There are 3 different classes which have concrete implementations of these methods.
Now after writing above structure, I found that some of the methods in the derived classes have identical implementations. So, I moved to the logic to my base class for these functions and made them virtual instead of pure virtual. Now, the implementations do not need to repeat in the derived classes. This compiles and executes fine.
My base class is a mixture of pure virtual and virtual methods, is it a good design approach to follow a structure like this?
It's absolutely fine, although a pattern does seem to have emerged where you would put all and only your pure virtual functions in a class to be regarded as more of an interface.
You would then define a class that implements the "common" parts of that interface, and have your 3 classes inherit from that class.
Over time, it seems that this lends itself to code that is more scalable and easier to maintain.
Java, out of interest, pretty much forces the use of this pattern.
It depends on the relationships between the classes, obviously. In other words, it is a design or implementation choice (i.e. up to you, as long as you can justify it sensibly). Technically, there is nothing preventing a class from having a mix of virtual, pure virtual, non-virtual, and static member functions.
If two derived classes override an inherited virtual function and implement it in the same way, then - yes - I would seriously consider providing that function into the base class. However, there are more questions I would ask - such as whether it makes sense for ALL derived classes to default to that implementation of the function. From a code reuse perspective, such a thing might make sense. From a design perspective, it may not.
That said, if it makes sense to treat a particular implementation of a function as a "default" (i.e. all derived classes default to using that, unless they override that function) then there is no harm in placing that definition in a base class.
As a crude example where what you suggest wouldn't make sense, consider this
class Aircraft
{
public:
virtual void Manoeuvre() = 0;
};
class Hornet : public Aircraft // F/A-18 hornet fighter aircraft
{
public:
void Manoeuvre();
};
class Tomcat : public Aircraft // F-14 tomcat fighter aircraft
{
public:
void Manoeuvre();
};
Let's say that, because of the fidelity of our modelling, that both derived classes had the same Manoeuvre() functions - they are both supersonic fighter aircraft (so will probably employ similar style of manoeuvre, albeit with different parameterisation). However, that is not sufficient to move their Manoeuvre() function to the base class, because there are aircraft that are not supersonic fighters, such as
class Hercules : public Aircraft // C-130 hercules cargo plan
{
public:
void Manoeuvre();
};
In this case, it does not make sense for a Hercules to inherit manoeuvring capability of a supersonic fighter, or vice versa. So it doesn't make sense for this to be supplied by the Aircraft class.
In this case, I might consider introducing intermediate classes, such as Fighter (which could be a common base of Hornet and Tomcat, but not Hercules) and - if I sought to represent multiple types of cargo aircraft - possibly a CargoPlane to be a common base for those. Then both Fighter and CargoPlane might derive from Aircraft, but Aircraft does not supply functionality that only makes sense to some aircraft types.
Incidental comment: although some people claim otherwise, there is nothing in C++ preventing a pure virtual function from having a definition (implementation). The meaning is that the function MUST be overridden by derived classes, but there is a default definition (which can be explicitly called by functions in derived classes) provided by the base class.
Yes, that is fine. However: If these are all the classes you have, there's no need to make the base class implementations virtual.

Use of making the base class polymorphic?

I know the keyword virtual makes the base class polymorphic and if I create an object and call a virtual function, corresponding function will be called based on the run time allocation but why should I create an object with different types. I mean
Base *ptr = new Derived;
ptr->virtualfunction(); //calls the function which has implemented in Derived class.
If I create an object so that
Derived *ptr = new Derived;
ptr->virtualfunction(); // which does the same without the need of making the function virtual.
Because you might want to store objects of different types together:
std::vector<std::unique_ptr<Base>> v;
v.push_back(make_unique(new DerivedA()));
v.push_back(make_unique(new DerivedB()));
v.push_back(make_unique(new DerivedC()));
Now, if you go over that vector:
for (auto& p : v) {
p->foo();
}
It will call foo() of DerivedA, B, and C appropriately.
Let's go with a simple example : Let's say you have
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
Now, let's say you want to be able to store in a vector (or any container) both Derived1 and Derived2 instances.
You have to use the base class in that case.
std::vector<Base*>
// or std::vector<std::unique_ptr<Base>>
The need for polymorphism is the need of processing different data in the same manner. Rather than reimplementing over and over the same algorithm for dataset with different shapes, wouldn't it be much easier to have only one implementation of that algorithm, and parameterize it with different operators?
That's the essence of polymorphism. You start with an algorithm, establish the interface it must interact with, and then build implementations of that interface. In C++ the notion of interface is implicit in every classes. Any class exposes one interface (though it may support many interfaces through its ancestors), and its descendants implement it as well. By making certain methods virtuals, the descendants may override and adapt them to their own internal structures, without modifying how the object is manipulated from the outside.
So polymorphism is really that, values which may adopt different shapes, and the means to access and manipulate them uniformally. The key point in answering your question is perhaps that the algorithm does not know which implepentation it is manipulating. You provide a trivial example where the code knows that it works with an instance of Derived, and thus may call its methods directly. In generic code, or code refering to an interface (so to speak), that knowledge does not exist, which forces the code to rely on the base class methods (and requires the programmer to ensure that the classes he plans to use with that code are well defined - ie. virtual - where needed).
There are many useful applications of polymorphism, but they all derive from the above principle:
heterogeneous dataset (as illustrated by other answers),
injection ( in which different implementations of the same interface may be swapped one for another at runtime),
testing (and more specifically mocking, in which classes which interact with a given class C are replaced by dummies which help test the correct behaviour of C),
to name a few. Note that compile time polymorphism (templates), and runtime polymorphism (virtual methods and inheritance) both achieve that goal, albeit in a different way, and with different pros and cons.

interface vs composition

I think I understand the difference between interface and abstract. Abstract sets default behavior and in cases of pure abstract, behavior needs to be set by derived class. Interface is a take what you need without the overhead from a base class. So what is the advantage of interface over composition? The only advantage I can think is use of protected fields in the base class. What am I missing?
Your title does not make sense, and your explanations are a bit blurry, so let's define the terms (and introduce the key missing one).
There are two different things going on here:
Abstract Class vs Interface
Inheritance vs Composition
Let us start with Interfaces and Abstract Classes.
An Abstract Class (in C++) is a class which cannot be instantiated because at least one its method is a pure virtual method.
An Interface, in Java-like languages, is a set of methods with no implementation, in C++ it is emulated with Abstract Classes with only pure virtual methods.
So, in the context of C++, there is not much difference between either. Especially because the distinction never took into account free-functions.
For example, consider the following "interface":
class LessThanComparable {
public:
virtual ~LessThanComparable() {}
virtual bool less(LessThanComparable const& other) const = 0;
};
You can trivially augment it, even with free functions:
inline bool operator<(LessThanComparable const& left, LessThanComparable const& right) {
return left.less(right);
}
inline bool operator>(LessThanComparable const& left, LessThanComparable const& right) {
return right.less(left);
}
inline bool operator<=(LessThanComparable const& left, LessThanComparable const& right) {
return not right.less(left);
}
inline bool operator>=(LessThanComparable const& left, LessThanComparable const& right) {
return not left.less(right);
}
In this case, we provide behavior... yet the class itself is still an interface... oh well.
The real debate, therefore, is between Inheritance and Composition.
Inheritance is often misused to inherit behavior. This is bad. Inheritance should be used to model a is-a relationship. Otherwise, you probably want Composition.
Consider the simple use case:
class DieselEngine { public: void start(); };
Now, how do we build a Car with this ?
If you inherit, it will work. However, suddenly you get such code:
void start(DieselEngine& e) { e.start(); }
int main() {
Car car;
start(car);
}
Now, if you decide to replace DieselEngine with WaterEngine, the above function does not work. Compilation fails. And having WaterEngine inherit from DieselEngine certainly feels ikky...
What is the solution then ? Composition.
class Car {
public:
void start() { engine.start(); }
private:
DieselEngine engine;
};
This way, noone can write nonsensical code that assumes that a car is an engine (doh!). And therefore, changing the engine is easy with absolutely no customer impact.
This means that there is less adherence between your implementation and the code that uses it; or as it is usually referred to: less coupling.
The rule of thumb is that in general, inheriting from a class which has data or implement behavior should be frown upon. It can be legitimate, but there are often better ways. Of course, like all rule of thumb, it is to be taken with a grain of salt; be careful of overengineering.
An interface defines how you will be used.
You inherit in order to be reused. This means you want to fit into some framework. If you don't need to fit into a framework, even one of your own making, don't inherit.
Composition is an implementation detail. Don't inherit in order to get the implementation of the base class, compose it. Only inherit if it allows you to fit into a framework.
An interface defines behaviour. An abstract class helps to implement behaviour.
In theory there is not a lot of difference between a pure abstract class with no implementation at all, and an interface. Both define an unimplemented API. However, pure abstract classes are often used in languages that don't support interfaces to provide interface like semantics (eg C++).
When you have the choice, generally an abstract base will provide some level of functionality, even if it's not complete. It helps implementation of common behaviour. The downside being you are forced to derive from it. When you are simply defining usage, use an interface. (There's nothing stopping you creating an abstract base that implements an interface).
Interfaces are thin, in C++ they can be described as classes with only pure virtual functions. Thin is good because
it reduces the learning curve in using or implementing the interface
it reduces the coupling (dependency) between the user and the implementor of the interface. Therefore, the user is really well insulated from changes in the implementation of the interface that they are using.
This, in conjunction with dynamic library linking, helps facilitate plug and play, one of the unsung but great software innovations of recent times. This leads to greater software interoperability, extensibility etc.
Interfaces can be more work to put in place. Justify their adoption when you have an important subsystem that could have more than one possible implementation, some day. The subsystem should in that case be used through an interface.
Reuse by means of inheiritance requires more knowlegde of the behaviour of the implementation you are overriding so there is greater "coupling". That said it is also a valid approach in cases where interfaces are overkill.
If type Y inherits from type X, then code which knows how to deal with objects of type X will, in most cases, automatically be able to deal with objects of type Y. Likewise, if type Z implements interface I, then code which knows how to use objects about which implement I, without having to know anything about them, will automatically be able to use objects of type Z. The primary purpose of inheritance and interfaces is to allow such substitutions.
By contrast, if object of type P contains an object of type Q, code which expects to work with an object of type Q will not be able to work on one of type P (unless P inherits from Q in addition to holding an object of that type). Code that expects to manipulate an object of type Q will be able to operate on the Q instance contained within P, but only if the code for P explicitly either supplies it to that code directly, or makes it available to outside code which does so.

is base class list the right place to indicate virtual inheritance?

I have never seen a class used as virtual and nonvirtual base (i.e. if some class is intended to be an ancestor then we usually know in advance about type of inheritance - virtual or nonvirtual).
So I suppose that there is an error-prone freedom in c++ to specialize "virtual" inheritance in base class list. It should be better to specify as "virtual" the base class itself
Or maybe I'm wrong?
If no, can anybody describe some technics to prevent accidental nonvirtual inheritance for such a "virtual" class?
Or there are some perspectives in upcoming c++ standards?
(Sorry if duplicate)
Some examples
1) ReferenceCounted class as base for all classes that some reference-count-based smartpointer can point to. We need to prevent duplicates of this base instances (and reference counters). There are no reasons to use this class as nonvirtual base, except of optimization.
2) A hierarchy of interfaces and corresponding hierarchy of implementations
(interfaces hierarchy must be "virtual" in this case)
// interfaces:
struct BaseIface{
void virtual func()=0;
};
struct DerivedIface: public virtual BaseIface{
void some_another_func()=0;
}
// implementations
class BaseImpl: public virtual BaseIface{
void virtual func(){....};
}
class DerivedImpl: public BaseImpl, public virtual DerivedIface{
void some_another_func(){...};
}
I suspect that in many cases nonvirtual inheritance is not a conceptual need, it used only to reduce virtual inheritance overhead (and sometimes for an ability to static_cast<> to drived :)
Note, that Java used ONLY virtual (in terms of c++) inheritance for interfaces, and I don't know any complains that this language lacks "nonvirtual" (it is esentially less expressive language than c++ but this "feature" is not it's main fault :).
There's not really much way you could do this in the base class (nor would you really want to). It's perfectly reasonable to use a base class for both virtual and non-virtual inheritance.
What you'd really like would be to specify the virtual inheritance in the most derived class, where currently has to be specified in the intermediate classes. Unfortunately, I don't see much way around that -- even though virtual inheritance becomes necessary (primarily) when a class derives from two (or more) other classes that each have a common base, the virtual inheritance really governs how those two other classes are compiled, so if you (only) specified it in the most derived class, you'd end up with something almost like export, where you might need to go back and re-compile those intermediate classes based on the most derived class specifying virtual inheritance (and have some way to store the intermediate classes compiled both ways since it might be used either or both ways).