I have a plain old CRPT (please don't get distracted by access restrictions - the question is not about them):
template<class Derived>
class Base {
void MethodToOverride()
{
// generic stuff here
}
void ProblematicMethod()
{
static_cast<Derived*>(this)->MethodToOverride();
}
};
that is as usual intended to be used like this:
class ConcreteDerived : public Base<ConcreteDerived> {
void MethodToOverride()
{
//custom stuff here, then maybe
Base::MethodToOverride();
}
};
Now that static_cast bothers me. I need a downcast (not an upcast), so I have to use an explicit cast. In all reasonable cases the cast will be valid since the current object is indeed of the derived class.
But what if I somehow change the hierarchy and the cast now becomes invalid?
May I somehow enforce a compile-time check that an explicit downcast is valid in this case?
At compile-time you can only check the static types, and that's what static_cast already does.
Given a Base*, it is only, and can only be, known at run-time what its dynamic type is, that is, whether it actually points to a ConcreteDerived or something else. So if you want to check this, it has to be done at runtime (for example by using dynamic_cast)
For extra safety, you could add a protected constructor to Base, to make sure that something is derived from it. Then the only problem would be for the really stupid:
class ConcreteDerived : public Base<SomeOtherClass>
but that should be caught by the first code review or test case.
To expand on what #Bo Persson said, you can do a compile time check in said constructor using for example Boost.TypeTraits or C++0x/11 <type_traits>:
#include <type_traits>
template<class Derived>
struct Base{
typedef Base<Derived> MyType;
Base(){
typedef char ERROR_You_screwed_up[ std::is_base_of<MyType,Derived>::value ? 1 : -1 ];
}
};
class ConcreteDerived : public Base<int>{
};
int main(){
ConcreteDerived cd;
}
Full example on Ideone.
It seems that there exists a way to check CRPT correctness at compile time.
By making Base abstract (adding some pure virtual method to Base) we guarantee that any Base instance is a part of some derived instance.
By making all Base constructors private we can prevent undesirable inheritance from Base.
By declaring Derived as friend of Base we allow the only inheritance expected by CRPT.
After this, CRPT downcast should be correct (since something is inherited from base and this "something" may be only Derived, not some other class)
Perhaps for practical purpose the first step (making Base abstract) is redundant since successful static_cast guaranties that Derived is somewhere in the Base hierarchy. This allows only an exotic error if Derived is iherited from Base <Derived> (as CRPT expects) but at the same time Derived creates another instance of Base <derived> (without inheritance) somewhere in Derived code (it can, because it is a friend). However, I doubt that someone may accidentally write such exotic code.
When you do something like below:
struct ConcreteDerived : public Base<Other> // Other was not inteded
You can create objects of the class (derived or base). But if you try calling the function, it gives compilation error related to static_cast only. IMHO it will satisfy all practical scenarios.
If I correctly understood the question, then I feel the answer is in your question itself. :)
I'm wondering whether there is a way to find out whether a class is a direct base of another class i.e. in Boost type trait terms a is_direct_base_of function. As far as I can see, Boost doesn't seem to support this kind of functionality, which leads me to think that it's impossible with the current C++ standard.
The reason I want it is to do some validation checking on two macros that are used for a reflection system to specify that one class is derived from another, as in the example code below.
header.h:
#define BASE A
#define DERIVED B
class A {};
class B : public A
{
#include <rtti.h>
};
rtti.h:
// I want to check that the two macro's are correct with a compile time assert
Rtti<BASE, DERIVED> m_rtti;
Although the macros seem unnecessary in this simple example, in my real world scenario rtti.h is a lot more complex.
One possible avenue would be to compare the size of the this pointer with the size of a this pointer cast to the base type and somehow trying to figure out whether it's the size of the base class itself away or something. (Yeah, you're right, I don't know how that would work either!)
I asked myself, "What C++ constructs do differentiate between direct inheritance vs. indirect?" It comes to mind that C++ constructors of derived types directly call constructors for their direct base(s) only. So code like this:
Derived::Derived() : Base() {}
Is only valid if Base is is a direct base of Derived. And since you are injecting the code of rtti.h into the body of Derived, you can tolerate the restriction that this technique is only directly visible within the derived class itself (i.e. it is not as general as a hypothetical type_traits::is_direct_base_of, but does not need to be).
So since we probably don't want to mess around with the default constructors per se, how about adding some special-purpose ones?
#define BASE A
#define DERIVED B
struct rtti_tag {}; // empty type
class A
{
protected:
A(rtti_tag) { assert(false); } // never actually called
};
#include <rtti.h>
class B : public A
{
IS_DIRECT_BASE_OF(DERIVED, BASE); // fails to compile if not true
};
rtti.h:
#define IS_DIRECT_BASE_OF(_B_, _A_) _B_(rtti_tag tag) : _A_(tag) \
{ assert(false); } // never actually called
This code compiles for me with g++ 4.2; if I insert a new class in the inheritance hierarchy, the assertion breaks and compilation fails with what I think is a reasonably descriptive diagnostic:
In constructor ‘B::B(rtti_tag)’:
error: type ‘A’ is not a direct base of ‘B’
...
This is our ideal inheritance hierarchy:
class Foobar;
class FoobarClient : Foobar;
class FoobarServer : Foobar;
class WindowsFoobar : Foobar;
class UnixFoobar : Foobar;
class WindowsFoobarClient : WindowsFoobar, FoobarClient;
class WindowsFoobarServer : WindowsFoobar, FoobarServer;
class UnixFoobarClient : UnixFoobar, FoobarClient;
class UnixFoobarServer : UnixFoobar, FoobarServer;
This is because the our inheritance hierarchy would try to inherit from Foobar twice, and as such, the compiler would complain of ambiguous references on any members of Foobar.
Allow me to explain why I want such a complex model. This is because we want to have the same variable accessible from WindowsFoobar, UnixFoobar, FoobarClient, and FoobarServer. This wouldn't be a problem, only I'd like to use multiple inheritance with any combination of the above, so that I can use a server/client function on any platform, and also use a platform function on either client or server.
I can't help but feel this is a somewhat common issue with multiple inheritance... Am I approaching this problem from completely the wrong angle?
Update 1:
Also, consider that we could use #ifdef to get around this, however, this will tend to yield very ugly code like such:
CFoobar::CFoobar()
#if SYSAPI_WIN32
: m_someData(1234)
#endif
{
}
... yuck!
Update 2:
For those who want to read more into the background of this issue, I really suggest skimming over the appropriate mailing list thread. Thing start to get interesting around the 3rd post. Also there is a related code commit with which you can see the real life code in question here.
It would work, although you'd get two copies of the base Foobar class. To get a single copy, you'd need to use virtual inheritance. Read on multiple inheritance here.
class Foobar;
class FoobarClient : virtual public Foobar;
class FoobarServer : virtual public Foobar;
class WindowsFoobar : virtual public Foobar;
class UnixFoobar : virtual public Foobar;
However, there are many problems associated with multiple inheritance. If you really want to have the model presented, why not make FoobarClient and FoobarServer take a reference to Foobar at construction time, and then have Foobar& FoobarClient/Server::getFoobar ?
Composition is often a way out of multiple inheritance. Take a example now:
class WindowsFoobarClient : public WindowsFoobar
{
FoobarClient client;
public:
WindowsFoobarClient() : client( this ) {}
FoobarClient& getClient() { return client }
}
However care must be taken in using this in the constructor.
What you are directly after here is virtual inheritance feature of C++. What you are in here for is a maintenance nightmare. This might not be a huge surprise since well-known authors like H. Sutter have been arguing against such use of inheritance for a while already. But this comes from direct experience with code like this. Avoid deep inheritance chains. Be very afraid of the protected keyword - it's use is very limited. This kind of design quickly gets out of hand - tracking down patterns of access to protected variable somewhere up the inheritance chain from lower level classes becomes hard, responsibilities of the code parts become vague, etc., and people who look at your code a year from now will hate you :)
You're in C++, you should get friendly with templates. Using the template-argument-is-a-base-class pattern, you'll not need any multiple inheritance or redundant implementations. It will look like this:
class Foobar {};
template <typename Base> class UnixFoobarAspect : public Base {};
template <typename Base> class WindowsFoobarAspect : public Base {};
template <typename Base> class FoobarClientAspect : public Base {};
template <typename Base> class FoobarServerAspect : public Base {};
typedef UnixFoobarAspect<FoobarClientAspect<Foobar>/*this whitespace not needed in C++0x*/> UnixFoobarClient;
typedef WindowsFoobarAspect<FoobarClientAspect<Foobar> > WindowsFoobarClient;
typedef UnixFoobarAspect<FoobarServerAspect<Foobar> > UnixFoobarServer;
typedef WindowsFoobarAspect<FoobarServerAspect<Foobar> > WindowsFoobarServer;
You might also consider using the curiously recurring template pattern instead of declaring abstract functions to avoid virtual function calls when the base class needs to call a function implemented in one of the specialized variants.
Use virtual inheritance, in the declaration of FoobarClient, FoobarServer, WindowsFoobar and UnixFoobar, put the word virtual before the Foobar base class name.
This will ensure there is always a single instance of Foobar no matter how many times it appears in your base class hierarchy.
Have a look at this search. Diamond inheritance is somewhat of contentuous issue and the proper solution dependes on individual situation.
I would like to comment on the Unix/Windows side of things. Generally one would #ifndef things out that are not appropriate for the particular platform. So you would end up with just Foobar compiled for either Windows or Unix using preprocessor directives, not UnixFoobar and WindowsFoobar. See how far you can get using that paradigm before exploring virtual inheritance.
Try this example of composition and inheritance:
class Client_Base;
class Server_Base;
class Foobar
{
Client_Base * p_client;
Server_Base * p_server;
};
class Windows_Client : public Client_Base;
class Windows_Server : public Server_Base;
class Win32 : Foobar
{
Win32()
{
p_client = new Windows_Client;
p_server = new Windows_Server;
}
};
class Unix_Client : public Client_Base;
class Unix_Server : public Server_Base;
class Unix : Foobar
{
Unix()
{
p_client = new Unix_Client;
p_server = new Unix_Server;
}
};
Many experts have said that issues can be resolved with another level of indirection.
There is nothing "illegal" about having the same base class twice. The final child class will just (literally) have multiple copies of the base class as part of it (including each variable in the base class, etc). It may result in some ambiguous calls to that base classes' functions, though, which you might have to resolve manually. This doesn't sound like what you want.
Consider composition instead of inheritance.
Also, virtual inheritance is a way to fold together the same base class which appears twice. If it really is just about data sharing, though, composition might make more sense.
You can access the variable with the qualified class name, but I forget the exact syntax.
However, this is one of the bad cases of using multiple inheritance that can cause you many difficulties. Chances are that you don't want to have things this way.
It's much more likely you want to have foobar privately inherited, have each subclass own a foobar, have foobar be a pure virtual class, or have the derived class own the things it currently defines or even define foobar on its own.
My style of coding includes the following idiom:
class Derived : public Base
{
public :
typedef Base super; // note that it could be hidden in
// protected/private section, instead
// Etc.
} ;
This enables me to use "super" as an alias to Base, for example, in constructors:
Derived(int i, int j)
: super(i), J(j)
{
}
Or even when calling the method from the base class inside its overridden version:
void Derived::foo()
{
super::foo() ;
// ... And then, do something else
}
It can even be chained (I have still to find the use for that, though):
class DerivedDerived : public Derived
{
public :
typedef Derived super; // note that it could be hidden in
// protected/private section, instead
// Etc.
} ;
void DerivedDerived::bar()
{
super::bar() ; // will call Derived::bar
super::super::bar ; // will call Base::bar
// ... And then, do something else
}
Anyway, I find the use of "typedef super" very useful, for example, when Base is either verbose and/or templated.
The fact is that super is implemented in Java, as well as in C# (where it is called "base", unless I'm wrong). But C++ lacks this keyword.
So, my questions:
is this use of typedef super common/rare/never seen in the code you work with?
is this use of typedef super Ok (i.e. do you see strong or not so strong reasons to not use it)?
should "super" be a good thing, should it be somewhat standardized in C++, or is this use through a typedef enough already?
Edit: Roddy mentionned the fact the typedef should be private. This would mean any derived class would not be able to use it without redeclaring it. But I guess it would also prevent the super::super chaining (but who's gonna cry for that?).
Edit 2: Now, some months after massively using "super", I wholeheartedly agree with Roddy's viewpoint: "super" should be private.
Bjarne Stroustrup mentions in Design and Evolution of C++ that super as a keyword was considered by the ISO C++ Standards committee the first time C++ was standardized.
Dag Bruck proposed this extension, calling the base class "inherited." The proposal mentioned the multiple inheritance issue, and would have flagged ambiguous uses. Even Stroustrup was convinced.
After discussion, Dag Bruck (yes, the same person making the proposal) wrote that the proposal was implementable, technically sound, and free of major flaws, and handled multiple inheritance. On the other hand, there wasn't enough bang for the buck, and the committee should handle a thornier problem.
Michael Tiemann arrived late, and then showed that a typedef'ed super would work just fine, using the same technique that was asked about in this post.
So, no, this will probably never get standardized.
If you don't have a copy, Design and Evolution is well worth the cover price. Used copies can be had for about $10.
I've always used "inherited" rather than super. (Probably due to a Delphi background), and I always make it private, to avoid the problem when the 'inherited' is erroneously omitted from a class but a subclass tries to use it.
class MyClass : public MyBase
{
private: // Prevents erroneous use by other classes.
typedef MyBase inherited;
...
My standard 'code template' for creating new classes includes the typedef, so I have little opportunity to accidentally omit it.
I don't think the chained "super::super" suggestion is a good idea- If you're doing that, you're probably tied in very hard to a particular hierarchy, and changing it will likely break stuff badly.
One problem with this is that if you forget to (re-)define super for derived classes, then any call to super::something will compile fine but will probably not call the desired function.
For example:
class Base
{
public: virtual void foo() { ... }
};
class Derived: public Base
{
public:
typedef Base super;
virtual void foo()
{
super::foo(); // call superclass implementation
// do other stuff
...
}
};
class DerivedAgain: public Derived
{
public:
virtual void foo()
{
// Call superclass function
super::foo(); // oops, calls Base::foo() rather than Derived::foo()
...
}
};
(As pointed out by Martin York in the comments to this answer, this problem can be eliminated by making the typedef private rather than public or protected.)
FWIW Microsoft has added an extension for __super in their compiler.
I don't recall seeing this before, but at first glance I like it. As Ferruccio notes, it doesn't work well in the face of MI, but MI is more the exception than the rule and there's nothing that says something needs to be usable everywhere to be useful.
Super (or inherited) is Very Good Thing because if you need to stick another inheritance layer in between Base and Derived, you only have to change two things: 1. the "class Base: foo" and 2. the typedef
If I recall correctly, the C++ Standards committee was considering adding a keyword for this... until Michael Tiemann pointed out that this typedef trick works.
As for multiple inheritance, since it's under programmer control you can do whatever you want: maybe super1 and super2, or whatever.
I just found an alternate workaround. I have a big problem with the typedef approach which bit me today:
The typedef requires an exact copy of the class name. If someone changes the class name but doesn't change the typedef then you will run into problems.
So I came up with a better solution using a very simple template.
template <class C>
struct MakeAlias : C
{
typedef C BaseAlias;
};
So now, instead of
class Derived : public Base
{
private:
typedef Base Super;
};
you have
class Derived : public MakeAlias<Base>
{
// Can refer to Base as BaseAlias here
};
In this case, BaseAlias is not private and I've tried to guard against careless usage by selecting an type name that should alert other developers.
I've seen this idiom employed in many code bases and I'm pretty sure I've even seen it somewhere in Boost's libraries. However, as far as I remember the most common name is base (or Base) instead of super.
This idiom is especially useful if working with class templates. As an example, consider the following class (from a real project):
template <typename TText, typename TSpec>
class Finder<Index<TText, PizzaChili<TSpec>>, MyFinderType>
: public Finder<Index<TText, MyFinderImpl<TSpec>>, Default>
{
using TBase = Finder<Index<TText, MyFinderImpl<TSpec>>, Default>;
// …
}
The inheritance chain uses type arguments to achieve compile-time polymorphism. Unfortunately, the nesting level of these templates gets quite high. Therefore, meaningful abbreviations for the full type names are crucial for readability and maintainability.
I've quite often seen it used, sometimes as super_t, when the base is a complex template type (boost::iterator_adaptor does this, for example)
is this use of typedef super common/rare/never seen in the code you work with?
I have never seen this particular pattern in the C++ code I work with, but that doesn't mean it's not out there.
is this use of typedef super Ok (i.e. do you see strong or not so strong reasons to not use it)?
It doesn't allow for multiple inheritance (cleanly, anyway).
should "super" be a good thing, should it be somewhat standardized in C++, or is this use through a typedef enough already?
For the above cited reason (multiple inheritance), no. The reason why you see "super" in the other languages you listed is that they only support single inheritance, so there is no confusion as to what "super" is referring to. Granted, in those languages it IS useful but it doesn't really have a place in the C++ data model.
Oh, and FYI: C++/CLI supports this concept in the form of the "__super" keyword. Please note, though, that C++/CLI doesn't support multiple inheritance either.
One additional reason to use a typedef for the superclass is when you are using complex templates in the object's inheritance.
For instance:
template <typename T, size_t C, typename U>
class A
{ ... };
template <typename T>
class B : public A<T,99,T>
{ ... };
In class B it would be ideal to have a typedef for A otherwise you would be stuck repeating it everywhere you wanted to reference A's members.
In these cases it can work with multiple inheritance too, but you wouldn't have a typedef named 'super', it would be called 'base_A_t' or something like that.
--jeffk++
After migrating from Turbo Pascal to C++ back in the day, I used to do this in order to have an equivalent for the Turbo Pascal "inherited" keyword, which works the same way. However, after programming in C++ for a few years I stopped doing it. I found I just didn't need it very much.
I was trying to solve this exact same problem; I threw around a few ideas, such as using variadic templates and pack expansion to allow for an arbitrary number of parents, but I realized that would result in an implementation like 'super0' and 'super1'. I trashed it because that would be barely more useful than not having it to begin with.
My Solution involves a helper class PrimaryParent and is implemented as so:
template<typename BaseClass>
class PrimaryParent : virtual public BaseClass
{
protected:
using super = BaseClass;
public:
template<typename ...ArgTypes>
PrimaryParent<BaseClass>(ArgTypes... args) : BaseClass(args...){}
}
Then which ever class you want to use would be declared as such:
class MyObject : public PrimaryParent<SomeBaseClass>
{
public:
MyObject() : PrimaryParent<SomeBaseClass>(SomeParams) {}
}
To avoid the need to use virtual inheritance in PrimaryParenton BaseClass, a constructor taking a variable number of arguments is used to allow construction of BaseClass.
The reason behind the public inheritance of BaseClass into PrimaryParent is to let MyObject have full control over over the inheritance of BaseClass despite having a helper class between them.
This does mean that every class you want to have super must use the PrimaryParent helper class, and each child may only inherit from one class using PrimaryParent (hence the name).
Another restriction for this method, is MyObject can inherit only one class which inherits from PrimaryParent, and that one must be inherited using PrimaryParent. Here is what I mean:
class SomeOtherBase : public PrimaryParent<Ancestor>{}
class MixinClass {}
//Good
class BaseClass : public PrimaryParent<SomeOtherBase>, public MixinClass
{}
//Not Good (now 'super' is ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public SomeOtherBase{}
//Also Not Good ('super' is again ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public PrimaryParent<SomeOtherBase>{}
Before you discard this as an option because of the seeming number of restrictions and the fact there is a middle-man class between every inheritance, these things are not bad.
Multiple inheritance is a strong tool, but in most circumstances, there will be only one primary parent, and if there are other parents, they likely will be Mixin classes, or classes which don't inherit from PrimaryParent anyways. If multiple inheritance is still necessary (though many situations would benefit to use composition to define an object instead of inheritance), than just explicitly define super in that class and don't inherit from PrimaryParent.
The idea of having to define super in every class is not very appealing to me, using PrimaryParent allows for super, clearly an inheritence based alias, to stay in the class definition line instead of the class body where the data should go.
That might just be me though.
Of course every situation is different, but consider these things i have said when deciding which option to use.
I don't know whether it's rare or not, but I've certainly done the same thing.
As has been pointed out, the difficulty with making this part of the language itself is when a class makes use of multiple inheritance.
I use this from time to time. Just when I find myself typing out the base class type a couple of times, I'll replace it with a typedef similar to yours.
I think it can be a good use. As you say, if your base class is a template it can save typing. Also, template classes may take arguments that act as policies for how the template should work. You're free to change the base type without having to fix up all your references to it as long as the interface of the base remains compatible.
I think the use through the typedef is enough already. I can't see how it would be built into the language anyway because multiple inheritence means there can be many base classes, so you can typedef it as you see fit for the class you logically feel is the most important base class.
I use the __super keyword. But it's Microsoft specific:
http://msdn.microsoft.com/en-us/library/94dw1w7x.aspx
I won't say much except present code with comments that demonstrates that super doesn't mean calling base!
super != base.
In short, what is "super" supposed to mean anyway? and then what is "base" supposed to mean?
super means, calling the last implementor of a method (not base method)
base means, choosing which class is default base in multiple inheritance.
This 2 rules apply to in class typedefs.
Consider library implementor and library user, who is super and who is base?
for more info here is working code for copy paste into your IDE:
#include <iostream>
// Library defiens 4 classes in typical library class hierarchy
class Abstract
{
public:
virtual void f() = 0;
};
class LibraryBase1 :
virtual public Abstract
{
public:
void f() override
{
std::cout << "Base1" << std::endl;
}
};
class LibraryBase2 :
virtual public Abstract
{
public:
void f() override
{
std::cout << "Base2" << std::endl;
}
};
class LibraryDerivate :
public LibraryBase1,
public LibraryBase2
{
// base is meaningfull only for this class,
// this class decides who is my base in multiple inheritance
private:
using base = LibraryBase1;
protected:
// this is super! base is not super but base!
using super = LibraryDerivate;
public:
void f() override
{
std::cout << "I'm super not my Base" << std::endl;
std::cout << "Calling my *default* base: " << std::endl;
base::f();
}
};
// Library user
struct UserBase :
public LibraryDerivate
{
protected:
// NOTE: If user overrides f() he must update who is super, in one class before base!
using super = UserBase; // this typedef is needed only so that most derived version
// is called, which calls next super in hierarchy.
// it's not needed here, just saying how to chain "super" calls if needed
// NOTE: User can't call base, base is a concept private to each class, super is not.
private:
using base = LibraryDerivate; // example of typedefing base.
};
struct UserDerived :
public UserBase
{
// NOTE: to typedef who is super here we would need to specify full name
// when calling super method, but in this sample is it's not needed.
// Good super is called, example of good super is last implementor of f()
// example of bad super is calling base (but which base??)
void f() override
{
super::f();
}
};
int main()
{
UserDerived derived;
// derived calls super implementation because that's what
// "super" is supposed to mean! super != base
derived.f();
// Yes it work with polymorphism!
Abstract* pUser = new LibraryDerivate;
pUser->f();
Abstract* pUserBase = new UserBase;
pUserBase->f();
}
Another important point here is this:
polymorphic call: calls downward
super call: calls upwards
inside main() we use polymorphic call downards that super calls upwards, not really useful in real life, but it demonstrates the difference.
The simple answer why c++ doesn't support "super" keyword is.
DDD(Deadly Diamond of Death) problem.
in multiple inheritance. Compiler will confuse which is superclass.
So which superclass is "D"'s superclass?? "Both" cannot be solution because "super" keyword is pointer.
This is a method I use which uses macros instead of a typedef. I know that this is not the C++ way of doing things but it can be convenient when chaining iterators together through inheritance when only the base class furthest down the hierarchy is acting upon an inherited offset.
For example:
// some header.h
#define CLASS some_iterator
#define SUPER_CLASS some_const_iterator
#define SUPER static_cast<SUPER_CLASS&>(*this)
template<typename T>
class CLASS : SUPER_CLASS {
typedef CLASS<T> class_type;
class_type& operator++();
};
template<typename T>
typename CLASS<T>::class_type CLASS<T>::operator++(
int)
{
class_type copy = *this;
// Macro
++SUPER;
// vs
// Typedef
// super::operator++();
return copy;
}
#undef CLASS
#undef SUPER_CLASS
#undef SUPER
The generic setup I use makes it very easy to read and copy/paste between the inheritance tree which have duplicate code but must be overridden because the return type has to match the current class.
One could use a lower-case super to replicate the behavior seen in Java but my coding style is to use all upper-case letters for macros.