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 method
Twowhich calls
Oneon
selfand
super`. 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 tosuper
,
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
Should I Compile With /Md or /Mt
Difference Between Atan and Atan2 in C++
Removing Leading and Trailing Spaces from a String
Efficient String Concatenation in C++
Creating All Possible K Combinations of N Items in C++
Global Variable Within Multiple Files
Explicit Specialization of Template Class Member Function
Splitting a C++ Std::String Using Tokens, E.G. ";"
How to Assign an Alias to a Function Name in C++
Why Is Default Constructor Called in Virtual Inheritance
Create Wcf Service For Unmanaged C++ Clients
Is Calling Destructor Manually Always a Sign of Bad Design
Determine the Size of a C++ Array Programmatically
How to Check If a C++ String Is an Int
Non-Blocking Console Input C++
Confused When Boost::Asio::Io_Service Run Method Blocks/Unblocks