Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm programming a library and I'm defining an interface for each class by making it's functions and destructor pure virtual. Now, over the time, I've experienced many disadvantages of this design (- just to name some of them: no static methods possible, a lot of virtual inheritence, and, of course, virtual functions are extremly slow.)
The only advantage I see in interfaces is to provide the user with a simple interface and hide the complex details behind them.
But considering all the disadvantages, I don't see why even big, known libraries are using interfaces. (f.e. Ogre 3D, Irrlicht and many other 3D libraries, where performance is the most important thing.)
My question is:
Is there a really convincing point which I'm missing why to use interfaces? Why do others do that? What is more common - using interfaces or
not using them?
Also, when using interfaces - is it valid to make some sort of "hybrid" design? Where classes relying on performance are implemented directly on the interface layer to avoid virtual function calls, and all other classes are implemented as usual? Or is this a bad design?
Your questions
Why use interfaces?
"Interfaces" isn't a well defined term in C++: some people consider any base class with virtual methods to be an interface, while others expect there to be no data members, or no public data members, or no private data members; a few people might say all members must be virtual, and others that they must be pure virtual.
There are pros and cons to each design decision:
base classes with virtual functions are C++'s mechanism for runtime polymorphism, which is a great reason to use them
keeping public data out of the base class preserves freedom to calculate the data on the fly
keeping private data out of the base class avoids having to change it therein when only the implementation changes; such changes force a client recompilation rather than a re-link (being able to just relink is especially useful when the implementation's in a shared object / library that's dynamically linked, as only an updated library need be distributed)
virtual dispatch makes it easy to implement state machines (changing the implementatino at run-time), as well as switching in mock implementations for testing
What is more common - using interfaces or not using them?
That's hugely dependent on the type of application, whether the data inputs or state naturally benefit from runtime polymorphism, and the design decisions made by the programmers' involved. C++ is used for such wildly divergent purposes that no general statement's meaningful.
Also, when using interfaces - is it valid to make some sort of "hybrid" design?
Yes - some "hybrid" approaches are listed under "mitigation" below.
Discussion of your remarks
"virtual functions are extremly slow"
Actual virtual dispatch is necessarily out-of-line, so can be about an order of magnitude worse than an inline call if doing something very simple (e.g. getter/setter for int member), but see mitigation below. (Often the optimiser can avoid virtual dispatch if the dynamic type of the variable involved is known at compile time).
"no static methods possible"
Each class can have static methods - there's just no way to invoke them polymorphically, but what would it even mean to do so? You must have some way to know the dynamic/runtime type as that's the basis for selecting which function to call....
Mitigation
There are a LOT of options for tuning performance - what you should often becomes obvious when you very carefully consider your actual performance problem. The following's a random smattering to give a taste of what's possible and occasionally useful....
Mitigation - granularity of work performed by virtual functions
Try to do as much work as possible per virtual function call. For example, a set_pixel function taking a single pixel would normally be bad interface design. A set_pixels function that can take an arbitrarily long list would be much better, but there're many other alternatives such as providing some kind of virtual drawing surface that the client code can work on without runtime polymorphic dispatch, then pass back the entire surface in one virtual function call.
Mitigation - handover to static-polymorphic code
You can manually orchestrate targeted (per performance profiling results) handover from run-time to compile-time polymorphism (albeit at the cost of manually maintaining a centralised handover routine.
Example
Assume a base class B with virtual void f();, and two derived D1, D2.
First, some polyrmophic algorithmic code that explicitly neuters virtual dispatch:
template <typename T>
struct Algo
{
void operator()(T& t)
{
.. do lots of stuff...
t.T::f(); // each t member access explicitly dispatched statically
...lots more...
}
};
Then, some code to dispatch to a static-type-specific instantiation of a specified algorithm based on dynamic type:
template <template <typename> class F>
void runtime_to_compiletime(B& b) {
if (D1* p = dynamic_cast<D1*>(&b))
F<D1>()(*p);
else if (D2* p = dynamic_cast<D2*>(&b))
F<D2>()(*p);
}
Usage:
D1 d1;
D2 d2;
runtime_to_compiletime<Algo>(d1);
runtime_to_compiletime<Algo>(d2);
Mitigation - orchestrate your own type information
If dynamic_cast is too slow in your implementation, you can get lightning fast switching on dynamic type - at the considerable cost of having to maintain it - as follows:
struct Base
{
Base() : type_(0) { }
int get_type() const { return type_; }
protected:
Base(int type) : type_(type) { }
int type_;
};
struct Derived : Base
{
Derived() : Base(1) { }
};
Then fast switching is trivial:
void f(Base* p)
{
switch (p->get_type())
{
... handle using static type in here ...
}
}
Mitigation - data in "interfaces"
Instead of virtual int f() const; to expose an int data member that only a few derived classes need to calculate on the fly, consider:
class Base
{
public:
Base() : virtual_f_(false) { }
int f() const { return virtual_f_ ? virtual_f() : f_; }
private:
int f_;
bool virtual_f_;
virtual int f() const { }
};
Interfaces are just one of the many mechanisms C++ provides to get reusability and extendibility.
Reuse.
If class A has a pointer to concrete class B, you cannot resuse class A withouth B.
Solution: you introduce an interface I implemented by B, and A has a pointer to I. In this way, you can reuse class A in your software (or in other applications) withouth B (please note that you bring I together with A so you need to implement it someway)
Extendibility.
If a class A has a pointer to concrete class B, class A is bounded to use the "algorithms" provided by B. In future, if you need to use different "algorithms", you are forced to modify A source code.
Solution: if A has a pointer to an interface I, you are free to change I implementation (eg. you can substitute B with C, both implementing I) withouth modifying A source code.
(By the way: mock implementations for testing are included in the extendibility case).
Let's recap:
you don't need to define an interface for each class of your software: you only need to put an interface when you need a hot spot for extendibility or reusability (yes: sadly this require you to think about your design instead of adopt blindly a rule...).
C++ offers many techniques to get the same results: instead of interfaces you can use templates or delegates (see std::function, boost::signal and so on).
the advantage you see in interfaces ("to provide the user with a simple interface and hide the complex details behind them") is best obtained by means of encapsulation. You don't need interface classes to get information hiding. It's enough that your classes don't export details in the public section.
I think you can use next approach: when you have multiply implementations of same interface and implementation selection should be performed at runtime (maybe those interface and implementation wrap some kind of "strategy" etc.) then you should use "interface-implementation" approach (with factory creation, etc.), when it's some kind of utility functionality - than you should avoid "interface-implementation" approach. You also should not forget about correct objects creation/destruction calls between libraries and main code. Hope this helps.
Using non intrusive polymorphism http://isocpp.org/blog/2012/12/value-semantics-and-concepts-based-polymorphism-sean-parent can help with problems of multiple inheritance and virtual inheritance by truly separating interface from implementation. This should eliminate the need for virtual inheritance. In my personal opinion virtual inheritance is a sign of bad/old design.
Also if you are using polymorphism in order to achieve the open closed principal then static polymorphism via CRTP can be much faster.
class Base {
virtual void foo(){
//default foo which the suer can override
}
void bar(){
foo();
}
}
class UserObject : public Base{
void foo() override{
//I needed to change default foo,
//this probably cannot be inlined unless the compiler is really
//good at devirtialization
}
}
becomes
template<typename T_Derived>
class Base {
virtual void foo(){
//default foo which the suer can override
}
void bar(){
static_cast<T_Derived*>(this)->foo();
}
}
class UserObject : public Base<UserObject>{
void foo() {
//I needed to change default foo, ths can be inlined no problem
}
}
One advantage with interfaces is that enables you to write unit tests. When writing a component that uses an interface, you can implement a simple fake version of the interface. The fake version can be given to the component to use during unit tests. This means unit tests will be fast as they don't really execute the library operation. Your fake implementation of the interface can be coded to return values and data to your component to cause it to execute certain code paths and the fake implementation can check that the component made expected calls to the interface.
This convinces me! Obviously, not all libraries are the same. Writing a fake version of a 3D graphics library might not always be useful as you really need to use your own eyes to see the image is correct as a unit test might be tricky to code to check the output is correct here. But, for many other applications unit tests are worth the extra work because they give you confidence to make changes to the code base and be sure it still works as behaves, and help ensure quality.
Related
I am trying to understand the real requirement of the usage of templates for policy based design. Going through the new templated designs in C++ I found that policy based class design is a highly suggested way of design which allows you to 'plug-in' different behaviors from policy classes. A minimal example is the following (a shortened version of the wiki):
template <typename LanguagePolicy>
class HelloWorld : private LanguagePolicy
{
using LanguagePolicy::message;
public:
// Behaviour method
void run() const
{
// policy methods
cout << message();
}
};
class LanguagePolicyA
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
//usage
HelloWorld<LanguagePolicyA> hello_worlda;
hello_worlda.run(); // prints "Hello, World!"
A quick analysis shows that just to get different plugable methods message() we are inheriting from a templated type whose definition can be provided by anyone (and identified at compile time).
But the same level of abstraction (and configurable methods) can be achieved without using a templated code and by the simple old school run time polymorphism as shown below.
class HelloWorld
{
LanguagePolicy *lp; //list of all plugable class
public:
HelloWorld(LanguagePolicy *lpn) {
lp = lpn;
}
// Behaviour method
void run() const
{
// policy methods
cout << lp->message();
}
};
class LanguagePolicy
{
protected:
virtual std::string message() const;
};
class LanguagePolicyA: LanguagePolicy
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
//usage
HelloWorld helloworld(new LanguagePolicyA);
helloworld.run();
Functionality and level of abstraction wise I don't see much of a difference in the two approach (even though the second approach has few extra lines of code for LanguagePolicy, I think it is needed for the other users to know the interface; otherwise understanding LanguagePolicy depends upon the documentation). But I do think the later to be 'clean' (coming from someone who has not used template much). This is because personally in my opinion non-templated classes are cleaner to look at and understand. An extremely good example is the popular library VTK (Visualization Tool Kit) which solves many different problems using the second approach. Even though there are not extensive documentations of VTK, most of us - its users, can just have a look into its class diagrams (sometimes they are quite big) and deduce behaviors of classes; and develop highly configurable and complicated pipelines in our application (can't imaging VTK to be template based :)). The opposite is libraries like STL/BOOST which I don't think is possible for anyone to be able to identify the working of the classes without the use of extensive documentation.
So my question is, is the template based policy design really superior (only in this scenario of policy based design) than virtual inheritance based? If so, when and why?
Both are valid ways of structuring, it actually depends on the requirements. E.g.
Runtime vs compile time polymorphism.
When do you want/can/have to achieve polymorphism ?
Performance overhead of virtual calls
Templates generate code that has no indirections
The actual usage of the class.
When you have to store heterogenous collections, a base class is needed, so you have to use inheritance.
A very good book on policy-based design (a bit dated but good nevertheless) is Modern C++ Design
Depends on the situation I guess... A possible downside of using templates is that the type should be known at compile-time:
HelloWorld<English> hw; // English is plugged at compile-time
In your second example, where you're using a pointer-to-base, this pointer might point to a variety of derived classes. What exactly it points to is not required to be known at compile-time and can therefore be determined by (user-)input at runtime. A possible down-side of this approach is virtual call overhead. In some applications, and on some platforms, this might be unwanted.
I am developing a 3D engine, suppose I have the following interface classes:
class IA {
public:
virtual ~IA() {}
virtual void doSomething() =0;
};
class IB {
public:
virtual ~IB() {}
virtual void bindA( IA* ) =0;
};
If you want to get a hold of an object of type "IA" or "IB" you must get them from a factory that is dependent on the backend API being used (e.g OpenGL).
The function IB::bindA(IA*) needs to access data from the implementation of IA, and to achieve that it does a static_cast to the implementation class and then directly access it's elements.
I was wondering what you think of this particular use of static_cast, do you think it's bad design? or do you think it's ok?.
The engine has to provide the same interface no matter what backend API is being used, so I don't think I could achieve this using virtual functions because I can't know beforehand what is needed by IB from IA.
Thanks :D
Edit
The thing is the engine has the following two classes:
class IHardwareBuffer {
public:
virtual ~IHardwareBuffer() {}
virtual void allocate( .... ) =0;
virtual void upload( .... ) =0;
};
and
class IMesh {
public:
virtual ~IMesh() {}
virtual bindBuffer( IHardwareBuffer* ) =0;
...
};
I "could" merge the IMesh and IHardwareBuffer classes together but that wouldn't make that much sense, since HardwareBuffer is just a "dumb" piece of memory with vertex data in it, and a Mesh is one or two HardwareBuffers with other data around them, like vertex format, material and such.
Having them be separate classes allows client code to have several meshes share a common HardwareBuffer and stuff like that.
It seems to me, that it's actually quite a bad idea from the design point of view.
If you use interfaces (or simulate them, as C++ doesn't have such language structure), you use them to publish these data, which are needed in other places. So if an object implementing IB has to cast IA to something to retreive its data, it's clearly a sign, that either IA publishes not enough data or the object implementing IA should also implement another, wider interface.
It's hard to tell, which option is better (or maybe if there is another), because we don't know the context here. Generally casting should be avoided if really not necessary and it suraly is not necessary here.
Edit:
The engine has to provide the same interface no matter what backend API is being used, so I don't think I could achieve this using virtual functions because I can't know beforehand what is needed by IB from IA. - this is a bad design.
Engine should be written in such way, that it's completely independent of implementation using it and vice versa. This is the whole point of using interfaces, base classes and polymorphism: you should be able to write another engine, swap it with existing one and everything should work without any changes in the implementation.
Edit (in response to comments):
I think, that a lot more clear solution is to cast to another interface, rather than specific implementation, ie:
class A : public IA, public IInternalA
{
// Implementation
};
// Inside B:
void B::Process(IA * a)
{
IInternalA ia = dynamic_cast<IInternalA *>(a);
if (ia != nullptr)
// Do something
}
This way you'll still be able to cut off from the implementation (for example, you'll be able to cut it into two independent parts), but inside your engine all the classes will know enough about each other to work properly.
An object has dynamic type, which can be read at runtime from its vtable, and static type, which is what you declare in the source code.
To safely cast based on dynamic type, use dynamic_cast. If you already know the dynamic type without looking at the vtable, then you can optimize the dynamic_cast into a static_cast. This is may meaningfully improve performance, and there's nothing wrong with doing so, as long as it's valid.
Code which casts to derived class references too often, though, might have issues with separation of concerns. The point of class hierarchies is to generalize.
I would recommend using references, not pointers, because the reference form of dynamic_cast will throw an exception if the cast is invalid. Then you can do something like this:
// Check dynamic type (and throw exception) for debug build only
#ifndef NDEBUG
#define downcast static_cast
#else
#define downcast dynamic_cast
#endif
Iopengl &glenv = downcast< Iopengl & >( myIA );
If you always know the actual dynamic type without going to the vtable (for example a global opengl flag), then the vtable is of course redundant. You could write the whole program with flags and branches replacing virtual dispatch.
The engine has to provide the same interface no matter what backend API is being used, so I don't think I could achieve this using virtual functions because I can't know beforehand what is needed by IB from IA.
As you already said, the abstract base class provides the interface and the derived class calls the backend. Your example is a little sketchy but it looks like IA and IB are interfaces, which you must define a backend-independent way if you are going to meet your goal… regardless of implementation.
OK now I think I understand your problem. You have several backends which have virtually (pun) nothing in common, and you need to use them in an engine that hides their differences.
Now the thing is, if two types have nothing in common, they should not inherit from a common base. And of course hacks like storing their pointers in a void* are just sweeping the dust under the carpet. So let's not do that.
So you need to provide a wrapper for each backend. All wrappers should conform to the same interface, but have nothing in common as far as their implementations are concerned. The factory should return a wrapper.
class IBackendWrapper
{
public:
... backend pure virtual functions ...
};
class OpenGLBackendWrapper : public IBackendWrapper
{
public:
... backend virtual function immplementations in terms of OpenGL ...
private:
... OpenGL data ...
};
class X11BackendWrapper : public IBackendWrapper
{
public:
... backend virtual function immplementations in terms of X11...
private:
... X11 data ...
};
class BackendFactory
{
public:
IBackendWrapper* getbackend();
};
Now your engine can use IBackendWrapper without much concern about concrete backends.
It could happen that each wrapper will be your entire engine, if your 3D abstraction is shallow. Then the engine class will degenerate to a simple forwarder. This is OK.
I understand that dynamic/static polymorphism depends on the application design and requirements. However, is it advisable to ALWAYS choose static polymorphism over dynamic if possible? In particular, I can see the following 2 design choice in my application, both of which seem to be advised against:
Implement Static polymorphism using CRTP: No vtable lookup overhead while still providing an interface in form of template base class. But, uses a Lot of switch and static_cast to access the correct class/method, which is hazardous
Dynamic Polymorphism: Implement interfaces (pure virtual classes), associating lookup cost for even trivial functions like accessors/mutators
My application is very time critical, so am in favor of static polymorphism. But need to know if using too many static_cast is an indication of poor design, and how to avoid that without incurring latency.
EDIT: Thanks for the insight. Taking a specific case, which of these is a better approach?
class IMessage_Type_1
{
virtual long getQuantity() =0;
...
}
class Message_Type_1_Impl: public IMessage_Type_1
{
long getQuantity() { return _qty;}
...
}
OR
template <class T>
class TMessage_Type_1
{
long getQuantity() { return static_cast<T*>(this)->getQuantity(); }
...
}
class Message_Type_1_Impl: public TMessage_Type_1<Message_Type_1_Impl>
{
long getQuantity() { return _qty; }
...
}
Note that there are several mutators/accessors in each class, and I do need to specify an interface in my application. In static polymorphism, I switch just once - to get the message type. However, in dynamic polymorphism, I am using virtual functions for EACH method call. Doesnt that make it a case to use static poly? I believe static_cast in CRTP is quite safe and no performance penalty (compile time bound) ?
Static and dynamic polymorphism are designed to solve different
problems, so there are rarely cases where both would be appropriate. In
such cases, dynamic polymorphism will result in a more flexible and
easier to manage design. But most of the time, the choice will be
obvious, for other reasons.
One rough categorisation of the two: virtual functions allow different
implementations for a common interface; templates allow different
interfaces for a common implementation.
A switch is nothing more than a sequence of jumps that -after optimized- becomes a jump to an address looked-up by a table. Exactly like a virtual function call is.
If you have to jump depending on a type, you must first select the type. If the selection cannot be done at compile time (essentially because it depends on the input) you must always perform two operation: select & jump. The syntactic tool you use to select doesn't change the performance, since optimize the same.
In fact you are reinventing the v-table.
You see the design issues associated with purely template based polymorphism. While a looking virtual base class gives you a pretty good idea what is expected from a derived class, this gets much harder in heavily templated designs. One can easily demonstrate that by introducing a syntax error while using one of the boost libraries.
On the other hand, you are fearful of performance issues when using virtual functions. Proofing that this will be a problem is much harder.
IMHO this is a non-question. Stick with virtual functions until indicated otherwise. Virtual function calls are a lot faster than most people think (Calling a function from a dynamically linked library also adds a layer of indirection. No one seems to think about that).
I would only consider a templated design if it makes the code easier to read (generic algorithms), you use one of the few cases known to be slow with virtual functions (numeric algorithms) or you already identified it as a performance bottleneck.
Static polimorphism may provide significant advantage if the called method may be inlined by compiler.
For example, if the virtual method looks like this:
protected:
virtual bool is_my_class_fast_enough() override {return true;}
then static polimophism should be the preferred way (otherwise, the method should be honest and return false :).
"True" virtual call (in most cases) can't be inlined.
Other differences(such as additional indirection in the vtable call) are neglectable
[EDIT]
However, if you really need runtime polymorphism
(if the caller shouldn't know the method's implementation and, therefore, the method can't be inlined on the caller's side) then
do not reinvent vtable (as Emilio Garavaglia mentioned), just use it.
I have an interface class similar to:
class IInterface
{
public:
virtual ~IInterface() {}
virtual methodA() = 0;
virtual methodB() = 0;
};
I then implement the interface:
class AImplementation : public IInterface
{
// etc... implementation here
}
When I use the interface in an application is it better to create an instance of the concrete class AImplementation. Eg.
int main()
{
AImplementation* ai = new AIImplementation();
}
Or is it better to put a factory "create" member function in the Interface like the following:
class IInterface
{
public:
virtual ~IInterface() {}
static std::tr1::shared_ptr<IInterface> create(); // implementation in .cpp
virtual methodA() = 0;
virtual methodB() = 0;
};
Then I would be able to use the interface in main like so:
int main()
{
std::tr1::shared_ptr<IInterface> test(IInterface::create());
}
The 1st option seems to be common practice (not to say its right). However, the 2nd option was sourced from "Effective C++".
One of the most common reasons for using an interface is so that you can "program against an abstraction" rather then a concrete implementation.
The biggest benefit of this is that it allows changing of parts of your code while minimising the change on the remaining code.
Therefore although we don't know the full background of what you're building, I would go for the Interface / factory approach.
Having said this, in smaller applications or prototypes I often start with concrete classes until I get a feel for where/if an interface would be desirable. Interfaces can introduce a level of indirection that may just not be necessary for the scale of app you're building.
As a result in smaller apps, I find I don't actually need my own custom interfaces. Like so many things, you need to weigh up the costs and benefits specific to your situation.
There is yet another alternative which you haven't mentioned:
int main(int argc, char* argv[])
{
//...
boost::shared_ptr<IInterface> test(new AImplementation);
//...
return 0;
}
In other words, one can use a smart pointer without using a static "create" function. I prefer this method, because a "create" function adds nothing but code bloat, while the benefits of smart pointers are obvious.
There are two separate issues in your question:
1. How to manage the storage of the created object.
2. How to create the object.
Part 1 is simple - you should use a smart pointer like std::tr1::shared_ptr to prevent memory leaks that otherwise require fancy try/catch logic.
Part 2 is more complicated.
You can't just write create() in main() like you want to - you'd have to write IInterface::create(), because otherwise the compiler will be looking for a global function called create, which isn't what you want. It might seem like having the 'std::tr1::shared_ptr test' initialized with the value returned by create() might seem like it'd do what you want, but that's not how C++ compilers work.
As to whether using a factory method on the interface is a better way to do this than just using new AImplementation(), it's possible it'd be helpful in your situation, but beware of speculative complexity - if you're writing the interface so that it always creates an AImplementation and never a BImplementation or a CImplementation, it's hard to see what the extra complexity buys you.
"Better" in what sense?
The factory method doesn't buy you much if you only plan to have, say, one concrete class. (But then again, if you only plan to have one concrete class, do you really need the interface class at all? Maybe yes, if you're using COM.) In any case, if you can forsee a small, fixed limit on the number of concrete classes, then the simpler implementation may be the "better" one, on the whole.
But if there may be many concrete classes, and if you don't want to have the base class be tightly coupled to them, then the factory pattern may be useful.
And yes, this can help reduce coupling -- if the base class provides some means for the derived classes to register themselves with the base class. This would allow the factory to know which derived classes exist, and how to create them, without needing compile-time information about them.
Use the 1st method. Your factory method in the 2nd option would have to be implemented per-concrete class and this is not possible to do in the interface. I.e., IInterface::create() has no idea exactly which concrete class you actually wish to instantiate.
A static method cannot be virtual, and implementing a non-static create() method in your concrete classes has not really won you anything in this case.
Factory methods are certainly useful, but this is not the correct use.
Which item in Effective C++ recommends the 2nd option? I don't see it in mine (though I don't also have the second book). That may clear up a mis-understanding.
I would go with the first option just because it's more common and more understandable. It's really up to you, but if your working on a commercial app then I would ask what my peers what they use.
I do have a very simple question there:
Are you sure you want to use a pointer ?
This question might seem unlogical but people coming from a Java background use new much often than required. In your example, creating the variable on the stack would be amply sufficient.
If I want to make a class adaptable, and make it possible to select different algorithms from the outside -- what is the best implementation in C++?
I see mainly two possibilities:
Use an abstract base class and pass concrete object in
Use a template
Here is a little example, implemented in the various versions:
Version 1: Abstract base class
class Brake {
public: virtual void stopCar() = 0;
};
class BrakeWithABS : public Brake {
public: void stopCar() { ... }
};
class Car {
Brake* _brake;
public:
Car(Brake* brake) : _brake(brake) { brake->stopCar(); }
};
Version 2a: Template
template<class Brake>
class Car {
Brake brake;
public:
Car(){ brake.stopCar(); }
};
Version 2b: Template and private inheritance
template<class Brake>
class Car : private Brake {
using Brake::stopCar;
public:
Car(){ stopCar(); }
};
Coming from Java, I am naturally inclined to always use version 1, but the templates versions seem to be preferred often, e.g. in STL code? If that's true, is it just because of memory efficiency etc (no inheritance, no virtual function calls)?
I realize there is not a big difference between version 2a and 2b, see C++ FAQ.
Can you comment on these possibilities?
This depends on your goals. You can use version 1 if you
Intend to replace brakes of a car (at runtime)
Intend to pass Car around to non-template functions
I would generally prefer version 1 using the runtime polymorphism, because it is still flexible and allows you to have the Car still have the same type: Car<Opel> is another type than Car<Nissan>. If your goals are great performance while using the brakes frequently, i recommend you to use the templated approach. By the way, this is called policy based design. You provide a brake policy. Example because you said you programmed in Java, possibly you are not yet too experienced with C++. One way of doing it:
template<typename Accelerator, typename Brakes>
class Car {
Accelerator accelerator;
Brakes brakes;
public:
void brake() {
brakes.brake();
}
}
If you have lots of policies you can group them together into their own struct, and pass that one, for example as a SpeedConfiguration collecting Accelerator, Brakes and some more. In my projects i try to keep a good deal of code template-free, allowing them to be compiled once into their own object files, without needing their code in headers, but still allowing polymorphism (via virtual functions). For example, you might want to keep common data and functions that non-template code will probably call on many occasions in a base-class:
class VehicleBase {
protected:
std::string model;
std::string manufacturer;
// ...
public:
~VehicleBase() { }
virtual bool checkHealth() = 0;
};
template<typename Accelerator, typename Breaks>
class Car : public VehicleBase {
Accelerator accelerator;
Breaks breaks;
// ...
virtual bool checkHealth() { ... }
};
Incidentally, that is also the approach that C++ streams use: std::ios_base contains flags and stuff that do not depend on the char type or traits like openmode, format flags and stuff, while std::basic_ios then is a class template that inherits it. This also reduces code bloat by sharing the code that is common to all instantiations of a class template.
Private Inheritance?
Private inheritance should be avoided in general. It is only very rarely useful and containment is a better idea in most cases. Common case where the opposite is true when size is really crucial (policy based string class, for example): Empty Base Class Optimization can apply when deriving from an empty policy class (just containing functions).
Read Uses and abuses of Inheritance by Herb Sutter.
The rule of thumb is:
1) If the choice of the concrete type is made at compile time, prefer a template. It will be safer (compile time errors vs run time errors) and probably better optimized.
2) If the choice is made at run-time (i.e. as a result of a user's action) there is really no choice - use inheritance and virtual functions.
Other options:
Use the Visitor Pattern (let external code work on your class).
Externalize some part of your class, for example via iterators, that generic iterator-based code can work on them. This works best if your object is a container of other objects.
See also the Strategy Pattern (there are c++ examples inside)
Templates are a way to let a class use a variable of which you don't really care about the type. Inheritance is a way to define what a class is based on its attributes. Its the "is-a" versus "has-a" question.
Most of your question has already been answered, but I wanted to elaborate on this bit:
Coming from Java, I am naturally
inclined to always use version 1, but
the templates versions seem to be
preferred often, e.g. in STL code? If
that's true, is it just because of
memory efficiency etc (no inheritance,
no virtual function calls)?
That's part of it. But another factor is the added type safety. When you treat a BrakeWithABS as a Brake, you lose type information. You no longer know that the object is actually a BrakeWithABS. If it is a template parameter, you have the exact type available, which in some cases may enable the compiler to perform better typechecking. Or it may be useful in ensuring that the correct overload of a function gets called. (if stopCar() passes the Brake object to a second function, which may have a separate overload for BrakeWithABS, that won't be called if you'd used inheritance, and your BrakeWithABS had been cast to a Brake.
Another factor is that it allows more flexibility. Why do all Brake implementations have to inherit from the same base class? Does the base class actually have anything to bring to the table? If I write a class which exposes the expected member functions, isn't that good enough to act as a brake? Often, explicitly using interfaces or abstract base classes constrain your code more than necessary.
(Note, I'm not saying templates should always be the preferred solution. There are other concerns that might affect this, ranging from compilation speed to "what programmers on my team are familiar with" or just "what I prefer". And sometimes, you need runtime polymorphism, in which case the template solution simply isn't possible)
this answer is more or less correct. When you want something parametrized at compile time - you should prefer templates. When you want something parametrized at runtime, you should prefer virtual functions being overridden.
However, using templates does not preclude you from doing both (making the template version more flexible):
struct Brake {
virtual void stopCar() = 0;
};
struct BrakeChooser {
BrakeChooser(Brake *brake) : brake(brake) {}
void stopCar() { brake->stopCar(); }
Brake *brake;
};
template<class Brake>
struct Car
{
Car(Brake brake = Brake()) : brake(brake) {}
void slamTheBrakePedal() { brake.stopCar(); }
Brake brake;
};
// instantiation
Car<BrakeChooser> car(BrakeChooser(new AntiLockBrakes()));
That being said, I would probably NOT use templates for this... But its really just personal taste.
Abstract base class has on overhead of virtual calls but it has an advantage that all derived classes are really base classes. Not so when you use templates – Car<Brake> and Car<BrakeWithABS> are unrelated to each other and you'll have to either dynamic_cast and check for null or have templates for all the code that deals with Car.
Use interface if you suppose to support different Break classes and its hierarchy at once.
Car( new Brake() )
Car( new BrakeABC() )
Car( new CoolBrake() )
And you don't know this information at compile time.
If you know which Break you are going to use 2b is right choice for you to specify different Car classes. Brake in this case will be your car "Strategy" and you can set default one.
I wouldn't use 2a. Instead you can add static methods to Break and call them without instance.
Personally I would allways prefer to use Interfaces over templates because of several reasons:
Templates Compiling&linking errors are sometimes cryptic
It is hard to debug a code that based on templates (at least in visual studio IDE)
Templates can make your binaries bigger.
Templates require you to put all its code in the header file , that makes the template class a bit harder to understand.
Templates are hard to maintained by novice programmers.
I Only use templates when the virtual tables create some kind of overhead.
Ofcourse , this is only my self opinion.