Using “super” in C++

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. I would upvote his answer twice, but I guess I can't.

share | improve this question
 
fixed per Adam's comment –  Michael Burr  Oct 7 '08 at 21:56
 
@Adam and Mike B: Of course... I guess this means I should go to sleep... :-p .... Thanks for the remark and correction !!! –  paercebal  Oct 7 '08 at 21:59
 
Awesome! Exactly what I was looking for. Don't think I've ever needed to use this technique until now. Excellent solution for my cross-platform code. –  AlanKley  Oct 22 '08 at 14:49
 
Thanks... I guess the question was a good one... :-p ... –  paercebal  Oct 22 '08 at 15:44

15 Answers

up vote 63 down vote accepted

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.

share | improve this answer
 
2  
D & E is indeed a good book. But it seems like I'll need to re-read it - I don't remember either story. –  Michael Burr  Oct 8 '08 at 4:37
1  
I remember three features that were not accepted discussed in D&E. This is the first (look up "Michael Tiemann" in the index to find the story), the two week rule is the second (look up "two week rule" in the index), and the third was named parameters (look up "named arguments" in the index). –  Max Lybbert  Oct 8 '08 at 17:49
 
Interesting historical note. +1. –  paercebal  Oct 9 '08 at 19:24
 
Nice discussion. –  vy32  Jul 5 '11 at 17:42

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.

share | improve this answer
 
1  
As for chaining super::super, as I mentionned in the question, I have still to find an interesting use to that. For now, I only see it as a hack, but it was worth mentioning, if only for the differences with Java (where you can't chain "super"). –  paercebal  Oct 8 '08 at 7:50
1  
As for the "private", good suggestion. + 1. –  paercebal  Oct 8 '08 at 7:51
1  
After I few months, I was converted to your viewpoint (and I DID had a bug because of a forgotten "super", like you mentionned...). You are quite right in your answer, including the chaining, I guess. ^_^ ... –  paercebal Jun 10 '09 at 16:45

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.)

share | improve this answer
 
Thanks for the remark. This side effect had escaped my notice. While it would probably won't compile for the constructor use, everywhere else, I guess, the bug would be there. –  paercebal  Oct 7 '08 at 22:02
8  
This is solved by making super private typedef. –  Loki Astari  Oct 7 '08 at 22:53
3  
However, private typedef will prevent chained use, mentioned in the original post. –  AndreyT  Oct 27 '09 at 0:21
1  
Running into this exact bug is what lead me to this question :( –  eventualEntropy  Sep 12 '12 at 20:33

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.

share | improve this answer
   

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.

share | improve this answer
 
I fully agree... :-) ... –  paercebal  Oct 7 '08 at 21:56
3  
Upvote just for the phrase, "there's nothing that says something needs to be usable everywhere to be useful."–  Tanktalus  Oct 7 '08 at 22:08
 
Agreed. It is useful. I was just looking at the boost type traits library to see if there was a way to generate the typedef via a template. Unfortunately, it doesn't seem like you can. –  Ferruccio  Oct 7 '08 at 22:15

FWIW Microsoft has added an extension for __super in their compiler.

share | improve this answer
 
A few developers here started pushing to use __super. At first I pushed back since I felt it was "wrong" and "non-stanadard". HOWEVER, I've grown to love it. –  Aardvark  Oct 8 '08 at 17:43
1  
I'm working on a windows app, and love the __super extension. It saddens me that the standards committee rejected it in favor of the typedef trick mentioned here, because while this typedef trick is good, it requires more maintenance than a compiler keyword when you change the inheritence hierarchy, and handles multiple inheritence correctly (without requiring two typedefs like super1 and super2). In short, I agree with the other commentor that the MS extension is VERY useful, and anybody using Visual Studio exclusively should strongly consider using it. –  Brian  Jan 10 '12 at 23:18

I've seen this idiom employed in many codes 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 ofsuper.

This idiom is especially useful if working with template classes. As an example, consider the following class (from a real project):

template <typename TText, typename TSpec>
class Finder<Index<TText, PizzaChili<TSpec> >, PizzaChiliFinder>
    : public Finder<Index<TText, PizzaChili<TSpec> >, Default>
{
    typedef Finder<Index<TText, PizzaChili<TSpec> >, Default> TBase;
    // …
}

Don't mind the funny names. The important point here is that the inheritance chain uses type arguments to achieve compile-time polymorphism. Unfortunately, the nesting level of these templates gets quite high. Therefore, abbreviations are crucial for readability and maintainability.

share | improve this answer
 
I had used the "super" lately for the very same reason. The public inheritance was too painful to handle otherwise... :-) ... –  paercebal  Oct 9 '08 at 19:28

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.

share | improve this answer
 
I think your last code block should derrive from "MakeAlias<Base>" not "MakeBaseAlias<Base>," but otherwise I really like this trick. –  Brian  Jan 10 '12 at 23:25
 
public alias is a downside, as you're open to the bug mentioned in Roddy's and Kristopher's answers (e.g. you can (by mistake) derive from Derived instead of MakeAlias<Derived>) –  Alexander Malakhov  Mar 25 at 10:35

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)

share | improve this answer
 
You're right. I found the reference here. boost.org/doc/libs/1_36_0/libs/iterator/doc/… –  paercebal  Oct 7 '08 at 22:04

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.

share | improve this answer
   

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.

share | improve this answer
 
2  
As a counter-point, Perl has both multiple inheritance and SUPER. There is some confusion, but the algorithm that the VM goes through to find something is clearly documented. That said, I rarely see MI used where multiple base classes offer the same methods where confusion could arise anyway. –  Tanktalus  Oct 7 '08 at 22:10
 
Interesting. Thanks for pointing that out! –  Toji  Oct 8 '08 at 2:15
 
Microsoft Visual Studio implements the __super keyword for C++ whether or not it's for CLI. If only one of the inherited classes offers a method of the correct signature (the most common case, as mentioned by Tanktalus) then it just picks the only valid choice. If two or more inherited classes provide a function match, it doesn't work and requires you to be explicit. –  Brian  Jan 10 '12 at 23:23

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++

share | improve this answer
   

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.

share | improve this answer
   

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.

share | improve this answer
   

I use the __super keyword. But it's Microsoft specific:

http://msdn.microsoft.com/en-us/library/94dw1w7x.aspx

share | improve this answer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值