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.
Related
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.
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.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What C++ idioms should C++ programmers use?
After reading books like C++ Primer, Effective C++ and TC++PL I want to learn some important design patterns.
So, what are the famous design patterns that every C++ programmer should know?
C++-specific ones: RAII and PIMPL.
The obvious answer is the Gang-Of-Four patterns from the famous book. These are the same patterns that get listed all over the place.
http://en.wikipedia.org/wiki/Design_Patterns
Beyond that, have a look around Martin Fowlers web site...
http://martinfowler.com/
There's a fair bit on there - the "famous" one is probably "dependency injection". Most others are pretty domain specific, though.
"Mixin layers" can be interesting for C++. A template class takes its own base as a template parameter, so that the template can be used to add the same functionality to many different classes, or as a composition method so that various features can be easily included/excluded for a library. The curiously recurring template trick is sometimes used as well (the original base is the final fully-composed class) so that the various mixin layers can do some degree of "reflection", so that intermediate methods can be defined in terms of fully-composed member types etc. Of course it can be a bit prone to unresolvable cyclic dependencies, if you're not careful.
http://portal.acm.org/citation.cfm?id=505148
Note - "the original base" doesn't mean the original base class that's inhereted from as that would cause an illegal inheritance cycle - it's just a template parameter used to refer to, to access the types/constants/etc in the final result and perhaps for metaprogramming reflection techniques.
I honestly don't know at this point if I was confused when I wrote "base", or just chose a confusing word.
Read the Design Patterns: Elements of Reusable Object-Oriented Software.
In no particular order, the Gang of Four patterns I see and use most, are probably the following:
Composite
Template Method
Abstract Factory
Singleton (much hated, but everywhere)
Visitor
Builder
Proxy
I suggest reading Head First Design Patterns. It's a fun read, and you'll learn about a lot of the common design patterns.
The think pattern. It's a silver bullet.
What are the main and most important rules (pros and cons) I have to apply when I write a class that will be inherited by third party.
Thank you.
The basic rule is: Make Interfaces Easy to Use Correctly and Hard to Use Incorrectly. It's from the 3rd edition of Scott Meyers' excellent book Effective C++.
Here are a few more pretty good guidelines for class design.
Rules:
Don't. Avoid using inheritance wherever possible.
The class must have at least one virtual function. specifically the destructor must be virtual.
The class should probably be abstract.
SOLID...
S SRP Single responsibility principle, the notion that an object
should have only a single responsibility.
O OCP Open/closed principle, the notion that “software … should
be open for extension, but closed for modification”.
L LSP Liskov substitution principle, see also design by contract.
I ISP Interface segregation principle, the notion that “many client
specific interfaces are better than one general purpose interface.”
D DIP Dependency inversion principle, the notion that one should
“Depend upon Abstractions. Do not depend upon concretions.”
Dependency injection is one method of following this principle.
taken from http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29
(or whatever acronym's your flavour of the month;)
HTH
Andy
I'm coming from a Java background, so the rules on inheritance are a little different, but here's my perspective:
Don't be afraid of inheritance. Most languages have it in some form or another, it's a very powerful paradigm, and it only stays hard if you don't use it.
Don't assume you know how future developers are going to use your classes later. I can't begin to count how many times I've had to copy an entire class just because some method or member was private. It's "O" in Andy's answer above - and it's a HUGE point.