Using "Super" in C++

Using super in C++

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.

C++ equivalent of super ?

There is a convention of defining a super typedef in every class.

What exactly is super in Objective-C?

super

Essentially, it allows you to use the implementations of the current class' superclass.

For the gritty details of the Objective-C runtime:

[super message] has the following meaning:

When it encounters a method call, the
compiler generates a call to one of
the functions objc_msgSend,
objc_msgSend_stret, objc_msgSendSuper,
or objc_msgSendSuper_stret. Messages
sent to an object’s superclass (using
the super keyword) are sent using
objc_msgSendSuper; other messages are
sent using objc_msgSend. Methods that
have data structures as return values
are sent using objc_msgSendSuper_stret
and objc_msgSend_stret.

So yes, it is static, and not determined at runtime.

What are the rules for calling the base class constructor?

Base class constructors are automatically called for you if they have no argument. If you want to call a superclass constructor with an argument, you must use the subclass's constructor initialization list. Unlike Java, C++ supports multiple inheritance (for better or worse), so the base class must be referred to by name, rather than "super()".

class SuperClass
{
public:

SuperClass(int foo)
{
// do something with foo
}
};

class SubClass : public SuperClass
{
public:

SubClass(int foo, int bar)
: SuperClass(foo) // Call the superclass constructor in the subclass' initialization list.
{
// do something with bar
}
};

More info on the constructor's initialization list here and here.

C++ calling super class

it's ok to call it ClassA::getVar1().

However, if you want the java-way, you can make the method "virtual". This means whenever you write getVar1(), it doesn't depend on the Type you wrote in front of it (so at compile time) but it depends on the type of the object when you call it (at runtime). For this reason, c++ keeps an internal v-table to find the appropriate method. It's equivalent to the java way and called late-binding.

Objective C: Difference between self and super

self and super work quite differently: self means the calling object at runtime, while super means the superclass of the class where the method definition is. In both cases they are specifying where the search for a method should start, in the case of self the starting point is determined dynamically, in the super case it is known at compile time.

Here is a made up example:

@interface Grandparent : NSObject

- (void) One;

@end

@implementation Grandparent

- (void) One { NSLog(@"Grandparent One\n"); }

@end

@interface Parent : Grandparent

- (void) One;
- (void) Two;

@end

@implementation Parent

- (void) One { NSLog(@"Parent One\n"); }

- (void) Two
{
[self One]; // will call One based on the calling object
[super One]; // will call One based on the defining object - Parent in this case so will Grandparent's One
}

@end

@interface Child : Parent

- (void) One;

@end

@implementation Child

- (void) One { NSLog(@"Child One\n"); }

@end


@implementation FamilyAppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Child *c = [Child new];
[c Two]; // will call the Two inherited from Parent

Parent *p = [Parent new];
[p Two]; // will call Parent's Two
}

@end

So we have three classes; Grandparent, Parent and Child; each with a method One. Class Parent has a methodTwowhich callsOneonselfandsuper`. Running this produces:

2011-04-15 22:49:05.006 Family[1993:a0f] Child One
2011-04-15 22:49:05.009 Family[1993:a0f] Grandparent One
2011-04-15 22:49:05.009 Family[1993:a0f] Parent One
2011-04-15 22:49:05.010 Family[1993:a0f] Grandparent One

For the Child case the call [c Two] calls the method Two that Child inherits from its Parent - so we have inheritance.

Now as Two executes it first calls [self One] and self is an instance of Child, which has a One, so Child's One is executed - this is inheritance-based polymorphism; at the time of defining Parent's Two the future existence of Child is unknown but at execution time the call [self One] is able to call Child's method .

The next call in Two is [super One]. Now this is known to refer to Grandparent's One at the time of definition.

In general super doesn't refer to a method in the superclass (as it does in this example), but to the method an object whose type is the superclass would invoke, e.g. it could belong to, say, Greatgrandparent. However whatever method is called can be determined at compile time, as the ancestry of any class is known.

The calls [self *method*] and [super *method*] can even invoke the same method, found dynamically in the former case, and known statically in the latter.

Hopefully you now can apply inheritance, self and super to your example.

Using Super in an Objective C Category?

Categories extend the original class, but they don't subclass it, therefore a call to super doesn't find the method.

What you want is called Method Swizzling. But be aware that your code could break something. There's an article on Theocacao written by Scot Stevenson about Method Swizzling in the old Objective-C runtime, Cocoa with Love by Matt Gallagher has an article about Method Swizzling in the new Objective-C 2.0 runtime and a simple replacement for it.

Alternatively, you could subclass the class and then either use the subclass or use + (void)poseAsClass:(Class)aClass to replace the superclass. Apple writes:

A method defined by a posing class
can, through a message to super,
incorporate the superclass method it
overrides.

Be aware that Apple has deprecated poseAsClass: in Mac OS X 10.5.

Is calling super in a category the same as calling it in a subclass?

In order to understand this, it's probably important to understand the way an object is stored during runtime. There is a class object1, which holds all the method implementations, and separately, there is a structure with the storage for the instance's variables. All instances of a class share the one class object.

When you call a method on an instance, the compiler turns that into a call to objc_msgSend; the method implementation is looked up in the class object, and then run with the instance as an argument.

A reference to super takes effect at compile time, not run time. When you write [super someMethod], the compiler turns that into a call to objc_msgSendSuper instead of the usual objc_msgSend. This starts looking for the method implementation in the superclass's class object, rather than the instance's class object.2

A category simply adds methods to the class object; it has little or no relation to subclassing.

Given all that, if you refer to super inside of a category, it does indeed do the same thing that it would inside of a class -- the method implementation is looked up on the class object of the superclass, and then run with that instance as an argument.

Itai's post answers the question more directly, but in code:

@interface Sooper : NSObject {}
- (void) meth;
@end

@interface Sooper ()
- (void) catMeth;
@end

@interface Subb : Sooper {}
- (void) subbMeth;
@end

@interface Subb ()
- (void) catSubbMeth;
@end

@implementation Sooper
- (void) meth {
[super doIt]; // Looks up doIt in NSObject class object
}

- (void) catMeth {
[super doIt]; // Looks up doIt in NSObject class object
}
@end

@implementation Subb
- (void) subbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}

- (void) catSubbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
@end

1 See Greg Parker's writeup [objc explain]: Classes and meta-classes

2One important thing to note is that the method doesn't get called on an instance of the superclass. This is where that separation of methods and data comes in. The method still gets called on the same instance in which [super someMethod] was written, i.e., an instance of the subclass, using that instance's data; it just uses the superclass's implementation of the method.

So a call to [super class] goes to the superclass object, finds the implementation of the method named class, and calls it on the instance, transforming it into the equivalent of [self theSuperclassImplementationOfTheMethodNamedClass]. Since all that method does is return the class of the instance on which it was called, you don't get the superclass's class, you get the class of self. Due to that, calling class is kind of a poor test of this phenomenon.

This whole answer completely ignores the message-passing/method call distinction. This is an important feature of ObjC, but I think that it would probably just muddy an already awkward explanation.



Related Topics



Leave a reply



Submit