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 3 years ago.
Improve this question
Coming from a Java/python world with little or no C++ experience, I am used to work with interfaces to separate the contract that a class has from its implementation, for the sake of the Liskov substitution principle and dependency injection.
I am not going to go over all the benefits of interfaces in Java, or why they were introduced (lack of multiple inheritance) and not needed in C++ (see here for example).
I also found out how to have the equivalent of a Java interface in C++
My question is more about whether or not this is a good practice in a C++ environment.
As I understand it, there cannot be the equivalent of an interface without pure virtual methods. This means that bringing interfaces in C++ will introduce some overhead in the code (because virtual methods introduce an overhead).
Therefore, are interfaces based on pure virtual method a good thing? Is there maybe some other way to achieve the Liskov Substitution principle and dependency injection that I don't know of? using templates maybe?
For example, google test has it easy to mock virtual methods, but proposes a way of mocking non virtual methods.
I am trying to figure out if my coding habits are still relevant in my new C++ environment, or if I should adapt and change my paradigms.
[EDIT based on answers and comments]
I got part of the answer I was looking for (i.e. "yes/no with arguments"), and i guess I should clarify a bit more what I am still trying to figure out
Are there alternatives to using an interface-like design to do dependency injection?
Reversing the question: should one decide to go for an interface-based design, except when speed is absolutely crucial, when would one NOT want to do an interface based on pure virtual methods?
Notes:
I guess I'm trying to figure out if I'm too narrow minded thinking in terms of interfaces (hence my edit looking for alternatives).
I work in a C++ 11 environment
I would say interfaces are still a fine practice in C++. The overhead that virtual methods introduce is minimal, and as you will hear time and time again, premature optimization is a big mistake. Abstract base classes are a well-known, well-understood concept in C++ and favoring readable, common concepts over convoluted template metaprogramming can help you immensely in the long run.
That being said, I would try to avoid multiple inheritance. There are certain tricky issues that come with it, which is why Java explicitly forbids it for regular inheritance. A simple google search can give you more explanation.
If you have multiple unrelated classes and you'd like to call a method of the same name (let's say foo()) on each of them, then instead of an interface you can make a templatized function to do this.
class A {
void foo() {
// do something
}
};
class B {
void foo() {
// do something
}
};
template <typename T>
void callFoo(const T& object) {
object.foo();
}
int main() {
A a;
B b;
callFoo(a);
callFoo(b);
return 0;
}
Even though there is no explicit "contract" in callFoo() stating that the type must support .foo(), any object that you pass to it must support it or there will be a compile error. This is a commonly used way to duck-type objects at compile time and an alternative to interfaces for certain scenarios.
At the end of the day, as you learn more C++, you will use your own judgement to decide how you will accomplish the polymorphic behavior you want. There is no single right answer how to do it, just as there is no wrong answer either. Both abstract base classes and template duck typing are good tools that serve slightly different purposes.
Related
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 3 years ago.
Improve this question
Many nowadays speeches on C++ are about templates and theirs usage for compile-time polymorphism implementation; virtual functions and run-time polymorphism are almost not discussed.
We can use compile-time polymorphism in many situations. And because it gives us compile-time checks instead of possible run-time errors related to runtime polymorphism, and well as some (usually insignificant, however) performance benefit, it looks nowadays most widely use libraries prefer compile-time polymorhism over run-time one.
However, for me it looks like compile-time polymorphism implemented with C++ templates result in much less self-documented and readable code than virtual types hierarchy.
As real life example we can review boost::iostreams. It implements stream as template that accepts device class as an argument. It results a situation when implementation of specific functionality is divided in many classes and files in different folders, so investigation in such code is much more complex than if streams will form classes hierarchy with virtual functions like we have in Java and .NET Framework? What is benefit of compile-time polymorphism here? File stream is something that reads and writes file, stream is something that reads and writes (anything), it is classical example of types hierarchy, so why not to use single FileStream class that overloads some protected functions instead of dividing semantically united functionality into different files and classes?
Another example is boost::process::child class. It uses templated constructor to setup standard i/o and other process parameters. It is not well-documented, and it is not obvious from this function prototype what arguments in what format will this template accept; implementation of member functions similar to SetStandardOutput will be much better self-documented and result in faster compile time, so what is benefit of template usage here? Again, I compare this implementation to .NET Framework here. For member functions similar to SetStandardOutput it is enough to read single header file to understand how to use the class. For templated constructor of boost::process::child we have to read many small files instead.
There are a lot of examples similar to this one. For any reason, well known open source libraries almost never use virtual classes hierarchy and prefer to use compile-time polymorhism (primarily templates-based) like boost does.
The question: are there any clear guidelines what we have to prefer (compile-time or run-time polymorphism) in situations where we can use both ones?
Generally speaking, in 90% of situation templates and virtual functions are interchangeable.
First of all, we need a clarification what we are talking about. If you "compare" something, it must be in some criteria equivalent. My understand of your statement is not comparing virtual functions with templates but within the context of polymorphism!
Your examples are not well selected in that case and also dynamic cast is more a "big hammer" out of the toolbox as if we talk about polymorphism.
Your "template example" did not need to use templates as you have simple overloads which can be used without any templated code at all!
If we are talking of polymorphism and c++ we have at a first selection runtime-polymorphism and compile-time polymorphism. And for both we have standard solutions in c++. For runtime we go with virtual functions, for compile-time polymorphism we have CRTP as a typical implementation and not templates as a general term!
are there any comments or recommendations from C++ committee or any other authoritative source, when we have to prefer ugly syntax of templates over much more understandable and compact virtual functions and inheritance syntax?
The syntax isn't ugly if you are used to use it! If we are talking about implementing things with SFINAE, we have some hard to understand rules with template instantiation, especially often misunderstood deduced context.
But in C++20 we will have concepts, which can replace SFINAE in most contexts which is a great thing I believe. Writing code with concepts instead of SFINAE makes it more readable, easier to maintain and a lot easier to extend for new types and "rules".
Standard library if full of templates and has a very limited amount of virtual functions. Does it mean that we have to avoid virtual functions as much as possible and prefer templates always even if theirs syntax for some specific task is much less compact and much less understandable?
The question feels you misunderstood the C++ features. Templates allows use to write generic code while virtual functions are the C++ tool to implement runtime polymorphism. There is nothing which is 1:1 comparable.
While reading your example code, I would advice you to think again about your coding style!
If you want to write functions specific for different data types, simply use overloads as you did in your "template" example, but without the unneeded templates!
if you want to implement generic functions which works for different data types in the same code, use templates and if some exceptional code is needed for specific data types use template specialization for the selected specific code parts.
If you need more selective template code which needs SFINAE you should start implementing with c++20 concepts.
If you want to implement polymorphism decide to use run time or compile time polymorphism. As already said, for the first one virtual functions are the standard C++ tool to implement that and CRTP is one of standard solutions for the second one.
And my personal experience with "dynamic cast" is: Avoid it! Often it is a first hint that something is broken with your design. That is not a general rule but a check point to think again about the design. In rare cases it is the tool which fits. And in RTTI is not available for all targets and it has some overhead. On bare metal devices/embedded systems you sometimes can't use RTTI and also exceptions. If your code is intended to be used as a "platform" in your domain, and you have the mentioned restrictions, don't use RTTI!
EDIT: Answers from the comments
So, for now, with C++ we can make classes hierarchy with run-time polymorphism only.
No! CRTP builds also class hierarchies but for compile time polymorphism. But the solutions is quite different as you don't have a "common" base class. But as all is resolved in compile time, there is no technical need for the common base class. You simply should start reading about Mixins, maybe here: What are Mixins (as a concept) and CRTP as one of the implementation methods: CRTP article wikipedia.
don't know how to implemented something similar to virtual functions without run-time overhead.
See above CRTP and Mixin exactly implementing polymorphism without runtime overhead!
Templates give some possibility to do that.
Templates are only the base C++ tool. Templates are the same level as loops in C++. It is much to broad to say "templates" in this context.
So, if we need class hierarchy, does it mean that we have to use it even it will force us to use less compile time checks?
As said, a class hierarchy is only a part of the solution for the task to implement polymorphism. Think more in logical things to implement like polymorphism, serializer, database or whatever and the implementation solutions like virtual functions, loops, stacks, classes etc. "Compile time checks"? In most cases you don't have to write the "checks" your self. A simple overload is something like an if/else in compile time which "checks" for the data type. So simply use it out of the box, no template nor SFINAE is needed.
Or we have to use templates to implement some sort of compile-time classes hierarchy even it will make our syntax much less compact and understandable
Already mentioned: Template code can be readable! std::enable_if is much easier to read as some hand crafted SFINAE stuff, even both uses the same C++ template mechanics. And if you get familiar with c++ 20 concepts, you will see that there is a good chance to write more readable template code in the upcoming c++ version.
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 7 years ago.
Improve this question
I'm coming form java background, had a conversation today with one of our C++ developer regarding to convert an existing code to have a pure virtual methods (interface) and to use them as dependency injection all over the code for better decoupling.
He tried to convince me that we should use them only when there is a "logic" in the code and in case the code is just collecting information from the PC it is not necessary.
Long story short, I'm looking for good reasons why to refactor the code and use IoC and pure virtual method instead of leaving the working coupled code as is.
There are many reasons why you should or should not refactor existing code. Each situation is unique. If you are talking about some kind of project with large codebase and you want to refactor it's core which works good and properly tested than in 99% cases I'd recomend you don't do that. You can add more bugs to tested code without making really needed improvements.
If code is just collecting some information you can extract interface for testing class that uses this object. If you don't use unit tests for some reasons than leave it as it is.
Overall you oponent is probably right, make interfaces when you really need them and write clean code with easy dependency extraction.
Why use pure-virtual methods?
I try to write base class functions to provide default behaviour for all the interface methods. I am surprised by how often these defaults simply generate some error handling (using the locally accepted mechanism).
For one example, I worked on code that received commands to set led states. During development, the 'other software' sometimes would (mistakenly) request a colour explicitly dis-allowed by the requirements. ('Red' disallowed on status led 5) My default functions generated the appropriate error message, and identified which 'other software' sent the erroneous request.
There are also cases that in some way have no appropriate default behaviour. For these situations, I create pure-virtual methods. Declaring the method pure virtual is documenting the idea that the base class will not provide the functionality, and is therefore requiring that all derived class must provide some code to support this concept.
"A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class that is not abstract" - Wikipedia
good reasons why to refactor the code?
Readability.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
UPDATE: I have asked a narrower question here.
On pages 6-7 of Modern C++ Design, Andrei Alexandrescu gives a very fundamental discussion of the strengths and weaknesses of two C++ language features -- multiple inheritance and templates -- with respect to building flexible designs. He concludes:
Now compare the list of drawbacks of multiple inheritance with the list of drawbacks of templates. Interestingly, multiple inheritance and templates foster complementary tradeoffs. Multiple inheritance has scarce mechanics; templates have rich mechanics. Multiple inheritance loses type information, which abounds in templates. Specialization of templates does not scale, but multiple inheritance scales quite nicely. You can provide only one default for a template member function, but you can write an unbounded number of base classes.
I can sense that what Andrei says here is very important, but I cannot really understand what is being said without any examples to illustrate the points. This question is asking to provide simple examples to illustrate these points (please continue reading).
To make the question more specific, I would like to ask to please focus on the weaknesses of multiple inheritance. This is what Andrei has to say about them (the text in square brackets is mine as per my understanding of the context):
In such a setting [i.e. multiple inheritance], [to build a flexible SmartPtr,] the user would build a multithreaded, reference-counted smart pointer class by inheriting some BaseSmartPtr class and two classes: MultiThreaded and RefCounted. Any experienced class designer knows
that such a naïve design does not work.
Analyzing the reasons why multiple inheritance fails to allow the creation of flexible
designs provides interesting ideas for reaching a sound solution. The problems with assembling
separate features by using multiple inheritance are as follows:
Mechanics. There is no boilerplate code to assemble the inherited components in a controlled
manner. The only tool that combines BaseSmartPtr, MultiThreaded, and RefCounted
is a language mechanism called multiple inheritance. The language applies
simple superposition in combining the base classes and establishes a set of simple rules
for accessing their members. This is unacceptable except for the simplest cases. Most
of the time, you need to orchestrate the workings of the inherited classes carefully to
obtain the desired behavior.
Type information. The base classes do not have enough type information to carry on
their tasks. For example, imagine you try to implement deep copy for your smart
pointer class by deriving from a DeepCopy base class. But what interface would DeepCopy
have? It must create objects of a type it doesn’t knowyet.
State manipulation. Various behavioral aspects implemented with base classes must manipulate
the same state. This means that they must use virtual inheritance to inherit a
base class that holds the state. This complicates the design and makes it more rigid because
the premise was that user classes inherit library classes, not vice versa.
I would very much appreciate a simple example for each of the three items above. Each example would show both one limitation of multiple inheritance (e.g. poor mechanics) and how templates do not possess this limitation (Andrei wrote that "multiple inheritance and templates foster complementary tradeoffs").
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 9 years ago.
Improve this question
I'll get to the point and explain below.
What, if any, are the benefits of...
template<class T>
class myStack : public myList<T>...// my stack
over
template<class T, Container = deque<T> >
class stack...// C++ stack
Recently I was writing some code and was faced with an inheritance issue where I was exposing aspects of the base class that I would rather not. The specific example isn't important so I'll relate it to few semesters ago when I took a data structures class where we implemented our own list, stack, queue and others.
In this class we were to design a stack which was to inherit from a list. The problem with this was I was exposing public methods of the base that could potentially damage the stack's integrity. It may be that I'm a bit of a purist but having the insert() and remove() lying around in the stack was bothersome for me. I didn't have time to investigate it then but this time I thought I would consult the C++ standard to see how the stack was defined there. Low and behold I found the code above; it was an obvious solution that I overlooked.
Here's my view...
The C++ implementation is "better" because it allows the user the freedom to choose the underlying structure if desired and maintains a more pure stack in that it is clear only stack functionality available to the user and can be more guarded from unintended corruption. Are there more substantial, non-subjective reasoning behind the design choice, or inherit flaws in it?
The obvious benefit of mine is code re-use which is par for the course, I don't see that as an additional benefit the way I personally see the benefit of the freedom with the C++ implementation. I do see the over exposure (my words) of the base class as a con though. Are there more substantial, non-subjective reasoning behind the design choice, or inherit flaws in it?
Again, I'm not concerned with languages, I'm more concerned with weighing the pros/cons for my own designs.
C++ collections and Java collections are very different. Java collections have an obvious type hierarchy, whereas most C++ collection types do not extend any other class, and templates are extensively used to support multiple collection types.
Although I don't know for sure, I imagine that the Java library developers made Stack a subclass of Vector because a stack is a collection of elements in a well defined order, so acts like a list, and by subclassing Vector they could get most of the implementation of the stack for free. This also has the benefit that you can use stacks in places where you need a list or a vector, for example you could pass a stack to a function that takes a list and iterates over it. Of course, c++ stacks are not iterable, so there is (intentianal or not) a very different semantics between the two stacks.
Finally, for your own code, if you are considering whether B should inherit or contain A, first ask yourself if B is an A, or more specifically, if you would ever want to treat a B as an A by passing it to a function that expects an A, or returning it from a function that needs to return an A. If so you should use inheritance, otherwise you should probably use composition.
The Stack class, as well as Vector, are legacy containers. They are left-overs of JDK1.0, they are based on an older design of the utils library, and are inefficient because of synchronization.
The preferred implementation of Stack in Java is given by implementations of the Deque interface (mainly ArrayDeque and LinkedList). You get the difference: in C++ one says that an stack has a given implementation. In Java one declares a class implementing the desired interface:
class ArrayDeque<E> extends AbstractCollection<E>
implements Collection<E>, Deque<E>, Queue<E> //etc
When using such classes, always take the less specialized interface possible, for instance:
Deque<String> stack = new LinkedList<String>();
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a program that uses opencv functions such as calibratecamera. Now I am working on the final version of my code, and I was wondering if instead of calling opencv's functions I inherit them in my classes would make my program 'better' ?
As pointed out in the comments, your question is very "general" and somehow confused. However, there is a general answer to the question "is it better to inherit?". Of course, being a general answer, it is oversimplified and might not apply to your case.
Item 58 in "C++ Coding Standards" (Sutter, Alexandrescu), is titled
Prefer composition to inheritance
You can find similar advice in several other books too.
The reason they give for making their case is:
Avoid inheritance taxes: Inheritance is the second-tightest coupling relationship in
C++, second only to friendship. Tight coupling is undesirable and should be
avoided where possible. Therefore, prefer composition to inheritance unless you
know that the latter truly benefits your design.
So, the general advise is to try and avoid inheritance as much as possible, and always being conservative on using it, unless you have a very strong case for it. For instance, you have a case for the use of public inheritance if you are modelling the so called "is-a" relationship. On the other hand, you have a case for using nonpublic inheritance if you are in one of the following situations:
If you need to override a virtual function
If you need access to a protected member
or in other less frequent cases.
Whatever your final choice is, be sure to only inherit from classes that have been designed in order to be base classes. For instance, be sure that the base class destructor is virtual. As the cited book poses it:
Using a standalone class as a base is a serious design error and
should be avoided. To add behavior, prefer to add nonmem-ber
functions instead of member functions (see Item 44). To add state,
prefer composition instead of inheritance (see Item 34). Avoid
inheriting from concrete base classes
OpenCV is a library with well defined API. If you have an existing application that uses functions bundled within this library and you don't have a valid reason for adding an additional functionality to them, there is no advantage that you could gain by wrapping them.
If you want to change the interface because you think it will make your code cleaner, I would worry about the maintenance in case the API will change in the future.
While changing the design of your applications, your decisions should be based on specific reasons. "I want to make my program better" is too abstract one.