Is it ppssible to implement a concatenative inheritance or at least mixins in C++?
It feels like it is impossible to do in C++, but I cannot prove it.
Thank you.
According to this article:
Concatenative inheritance is the process of combining the properties
of one or more source objects into a new destination object.
Are we speaking of class inheritance ?
This is the basic way public inheritance works in C++. Thanks to multiple inheritance, you can even combine several base classes.
There might be some constraints however (e.g. name conflicts between different sources have to be addressed, depending on use case you might need virtual functions, and there might be the need to create explicitly a combined constructors).
Or is inheritance from instantiated objects meant ?
If it's really about objects and not classes, the story is different. You cannot clone and combine object of random type with each other, since C++ is a strongly typed language.
But first, let's correct the misleading wording. It's not really about concatenative inheritance, since inheritance is for classes. It's rather "concatenative prototyping", since you create new objects by taking over values and behaviors of existing objects.
To realize some kind of "concatenative prototyping" in C++, you therefore need to design it, based on the principle of composition, using a set of well defined "concatenable" (i.e. composable) base classes. This can be achieved, using the prototype design pattern together with the entity-component-system architecture.
What's the purpose
You are currently looking for this kind of construct, probably because you used it heavily in a dynamically typed language.
So keep in mind the popular quote (Mark Twain ? Maslow ? ):
If you have a hammer in your hand, every problem looks like nails
So the question is what you are really looking for and what problem you intend to solve. IMHO, it cannot be excluded that other idioms could be more suitable in the C++ world to achieve the same objective.
Related
As I have understood are concepts quite similar to interfaces: Like interfaces, concepts allow to define some kind of a set of methods/concept/interface, which the implementation expects and needs to perform its task. Both strengthen the focus on semantic needs.
While Bjarne and many other people seem to see concepts as way to get rid of uses of enable_if and generally complicated templates, I wonder if it makes sense to use it instead of interfaces/pure abstract classes.
Benefits are obvious:
no runtime cost (v-table)
kind of duck typing, because the suitable classes do not have to implement the interface
even relationships between parameters (which interfaces do not support at all)
Of course a disadvantage is not far away:
no template definition checking for concepts, at least for now
…
I wonder if there are more of these and if it would make no sense after all.
I know that there are similar questions, but they are not specific with their purpose nor is it answered in an answer. I also found other people who had the same idea, but at no point there is somebody who really encourages/discourages this, let alone argues on it.
If you are using abstract classes for their intended purpose, then there is pretty much no way to replace them with concepts. Abstract base classes are for runtime polymorphism: the ability to, at runtime, have the implementation of an interface be decoupled from the site(s) where that interface gets used. You can use user input or data from a file to determine which derived class instance to create, then pass that instance to some other code that uses a pointer/reference to the base class.
Abstract classes are for defining an interface for runtime polymorphism.
A template is instantiated at compile-time. As such, everything about its interface must be verified at compile-time. You cannot vary which implementation of an interface you use for a template; it's statically written into your program, and the template gets instantiated with exactly and only the types you spell out in your code. That's compile-time polymorphism.
Concepts are for defining an interface for compile-time polymorphism. They don't work at runtime.
If you've been using abstract base classes for compile-time polymorphism, then you've been doing the wrong thing, and you should have stopped well before concepts came out.
I've watched some videos and articles on metaclasses , and IMO they have the potential to replace inheritance and providing a way to do a sort of compile-time inheritance.
With metaclasses i can provide interfaces, default function implementation, and even correctness of implementation(not the body of the functions of course) of class during compilation. So there is something that can't be done in metaclasses that can be done with inheritance, polymorphism and OO stuff?
Just as a general remark, I write as a "frequent" author of Python metaclasses:
Metaclasses are not meant for "day to day" use, and however C++ metaclasses may not be the same as they are in Python, I can hardly see such a concept be used to replace something as common as inheritance.
Inheritance have their roles. If you are in need for special rules for a whole class hierarchy, it may be useful to have a metaclass to specify these rules to start with. (The first example in both the C++ proposal and on most explanatory material I've browsed are "interfaces" - which mandates that all methods are virtual). So, supposing you find out a special rule you want in a whole set of classes in your system and can express that using a metaclass, that does not preclude you from creating a single base-class from that metaclass, and create all other classes with "normal" inheritance, if what will change from one such class to another are just the usual method overriding and specialization: inheritance still will be simpler, both to code, as to whoever reads your code, as for the toolchain echo system that evolved around C++ in decades of language existance.
So, yes, metaclass inheritance could, for all that is, allow you to encode all common capabilities of your classes in the metaclass, and them just create new classes using this metaclass, instead of inheritance. But there are no motives on Earth to do that.
Just to bridge back to Python, where I am well acquainted with the concept: the language recently took one step in the opposite direction - by enabling two mechanisms in normal inheritance in version 3.6 that were previously only possible through metaclasses, and in doing that, further reducing the use cases where metaclasses are needed just due to the extra complication they necessarily call for.
I was looking at a few sources for STL implementations (SGI, STLport, libc++) and saw a few design patterns that seemd common to all or most implementations, but I could find no reason for. I assume there must be a good reson, and want to know what it is:
Many classes, including vector and list_iterator among others, were implemented as 2 classes, e.g. list_iterator_base with part of the functionality, and then list_iterator which inherits list_iterator_base with the rest of the interface. What is the point? It seems it could be done jut as easily in one class.
The iterators seem to not make use of the iterator class. Is there some performance penalty to using it?
Those are 2 questions I found in just a quick skim. If anyone knows of a good resource explaining the implementation rationale of a STL implementation, I will be happy to hear of it.
The answers are fairly straight forward:
STL is all about generic programming. The key idea is not to have duplicate code. The immediate goal is to not have duplicate source code but as it turns out it also makes sense to not duplicate binary code. Thus, it is quite common that STL components factor commonly used parts out and use them. The links for a list class or the type independent attributes of a vector are just two examples. For vectors there are even multiple layers: some parts are entirely independent of the type (e.g., the size), others only need the type itself (e.g., all the accessors, the iterators, etc.), and some parts need to know how to deal with resource allocation (e.g., insertion and destruction needs to know about the allocator being used).
It turns out that std::iterator<...> doesn't really work: The types defined in base classes depending on template parameters are not directly accessible in class template deriving from such a base. That is, the types need to be qualified with the base class and need to be marked as types using typename. To make matters worse, users could in theory allocate objects of the derived class and release them through a pointer to std::iterator<...> (yes, that would be a silly thing to do). That is, there is no benefit but a potential drawback, i.e., it is best avoided.
That said, I'm not aware of any good resource covering the techniques of implementing generic libraries. Most of the details applied in STL implementations were independently invented by multiple people but the literature on Generic Programming is still relatively scarce. I don't think that any of the papers describing STL actually discuss implementation techniques: They normally concentrate on design details. Given that only very few people seem to understand what STL is about, it isn't a big surprise that authors tend to concentrate on describing what STL is rather than how to implement it.
I wonder if what I'm currently doing is a shame for C++, or if it is OK.
I work on a code for computational purpose. For some classes, I use a normal inheritance scheme with virtuality/polymorphism. But I need some classes to do intensive computation, and it would be great to avoid overhead due to virtuality.
Basically, I want to use this classes without pointers or redirection : inheritance is just here to avoid many copy/paste of code (the file size of the base class is like 60Ko (which is a lot of code)). So no virtual functions, and no virtual desctructor.
I wonder if it is perfectly OK from a C++ point of view or if it can create side effects (the concerned classes will be used a lot in the program).
Thank you very much.
Using polymorphism in C++ is neither good nor bad. Polymorphism serves a purpose, as does a lack of polymorphism. There is nothing wrong with using inheritance without using polymorphism on its own.
Since polymorphism serves a purpose, and the lack of polymorphism also serves a purpose, you should design your classes with those purposes in mind. If, for example, you need runtime binding of behavior to class instances, you need polymorphism.
That all being said, there are right and wrong reasons for choosing one approach over the other. If you are designing your classes without polymorphism strictly because you want to "avoid overhead" that is likely a wrong reason. This is an instance of premature optimization so long as you are making design changes or decisions without having profiled your code and proved that polymorphism is an actual problem.
Design by architectural requirements first. Later go back and refactor if the design proves to be non-performant.
I would rephrase the question:
What does inheritance brings that composition could not achieve if you eschew polymorphism ?
If the answer is nothing, which I suspect, then perhaps that inheritance is not required in the first place.
Not using virtual members/inheritance is perfectly ok. C++ is designed to entertain vast audience and it doesn't restrict anyone to particular paradigm.
You can use C++ to code procedural, generic, object-oriented or any mix of them. Just try to make best out of it.
I'm currently doing is a shame for C++, or if it is OK.
Not at all.
Rather if you don't need OO design and still imposing it just for the sake of it, would be a shame.
Basically, I want to use this classes without pointers or redirection ...
In fact you are going in right direction. Using pointers, arrays and such low level features are better suited for advance programming. Use instead like std::shared_ptr, std::vector, and standard library containers.
Basically, you are using inheritance without polymorphism. And that's ok.
Object-oriented programming has other feature than polymorphism. If you can benefits from them, just use them.
In general, it is not a good idea to use inheritance to reuse code. Inheritance is rather to be used by code that was designed to use your base class. I would suggest a different approach to the problem. Consider some of the alternatives, like composition, changing the functionality to be implemented in free functions rather than a base class, or static polymorphism (through the use of templates).
It's not a performance problem until you can prove it.
Check out that answer and the "Fastest possible delegates" article.
A class design guideline found in Sutter&Alexandrescu's coding standards book, among others, is to make base classes abstract, such that one cannot instantiate them. This is to prevent a.o. slicing and problems with polymorphic assignment and copying.
However, when using a class library like e.g. Qt, it is common practice to inherit from concrdete classes from the library to add additional behavior. For example one would create a class MyListBox which inherits from QListBox, adding application-specific behavior for all list boxes in my application.
How is can this common practice be reconciled with the advice to have non-instantiatiable base classes?
Your very first sentence contains the answer you are looking for:
A class design guideline found in Sutter&Alexandrescu's coding standards book
(emphasis mine).
It's just that - a guideline, not a rule carved in stone.
If you have specific technical limitations, for example in the library you are using, you may ignore it if the given alternative at that particular moment is way worse (like having to use some pattern that triples the total amount of code or having to rewrite the library).
The whole point of my answer: All these patterns, guidelines and best practices are means by which you can reach your programming goal. They are not the goal, themselves.
That guideline only applies to base classes should not be instantiated (usually because doing so would make no sense). This is not the case in your example: for example, just because you inherited from QDialog doesn't mean that you wouldn't want to use plain old QDialogs elsewhere in the code.