95

Lately, I have done much programming in Java. There, you call the class you inherited from with super(). (You all probably know that.)

Now I have a class in C++, which has a default constructor which takes some arguments. Example:

class BaseClass { public: BaseClass(char *name); .... 

If I inherit the class, it gives me the warning that there is no appropriate default constructor available. So, is there something like super() in C++, or do I have to define a function where I initialize all variables?

7
  • 12
    There is no super() in C++, partly because you can have several base classes. Commented Aug 3, 2011 at 8:41
  • 4
    There is __super keyword in MSVC. Which works well even for multiple base classes, and emits error only when ambiguity is there. Commented Aug 3, 2011 at 9:02
  • 3
    @Ajay That is a MSVC extension, and not a standard c++ Commented Aug 3, 2011 at 9:23
  • 4
    @VJ, Yes, I explicitly mentioned MSVC. Initial underscoring implies it is not standard keyword. :) Commented Aug 3, 2011 at 9:28
  • I will upvote it, since it might help someone, even if that someone is not me. It is a good comment as it contributes relevant knowledge. Commented May 21, 2015 at 13:12

6 Answers 6

131

You do this in the initializer-list of the constructor of the subclass.

class Foo : public BaseClass { public: Foo() : BaseClass("asdf") {} }; 

Base-class constructors that take arguments have to be called there before any members are initialized.

Sign up to request clarification or add additional context in comments.

1 Comment

Well, to be pedantic, base-class constructors will be called in the initializer list before any members are initialized; if no base-class is provided, then it attempts to use the default constructor implicitly. If there is a default constructor for BaseClass, and no other constructor is in the initialization list, then the default will be called; it's not that the programmer has to call it.
44

In the header file define a base class:

class BaseClass { public: BaseClass(params); }; 

Then define a derived class as inheriting the BaseClass:

class DerivedClass : public BaseClass { public: DerivedClass(params); }; 

In the source file define the BaseClass constructor:

BaseClass::BaseClass(params) { //Perform BaseClass initialization } 

By default the derived constructor only calls the default base constructor with no parameters; so in this example, the base class constructor is NOT called automatically when the derived constructor is called, but it can be achieved simply by adding the base class constructor syntax after a colon (:). Define a derived constructor that automatically calls its base constructor:

DerivedClass::DerivedClass(params) : BaseClass(params) { //This occurs AFTER BaseClass(params) is called first and can //perform additional initialization for the derived class } 

The BaseClass constructor is called BEFORE the DerivedClass constructor, and the same/different parameters params may be forwarded to the base class if desired. This can be nested for deeper derived classes. The derived constructor must call EXACTLY ONE base constructor. The destructors are AUTOMATICALLY called in the REVERSE order that the constructors were called.

EDIT: There is an exception to this rule if you are inheriting from any virtual classes, typically to achieve multiple inheritance or diamond inheritance. Then you MUST explicitly call the base constructors of all virtual base classes and pass the parameters explicitly, otherwise it will only call their default constructors without any parameters. See: virtual inheritance - skipping constructors

Comments

23

You have to use initiailzers:

class DerivedClass : public BaseClass { public: DerivedClass() : BaseClass(<insert arguments here>) { } }; 

This is also how you construct members of your class that don't have constructors (or that you want to initialize). Any members not mentioned will be default initialized. For example:

class DerivedClass : public BaseClass { public: DerivedClass() : BaseClass(<insert arguments here>) , nc(<insert arguments here>) //di will be default initialized. { } private: NeedsConstructor nc; CanBeDefaultInit di; }; 

The order the members are specified in is irrelevant (though the constructors must come first), but the order that they will be constructed in is in declaration order. So nc will always be constructed before di.

Comments

5

Regarding the alternative to super; you'd in most cases use use the base class either in the initialization list of the derived class, or using the Base::someData syntax when you are doing work elsewhere and the derived class redefines data members.

struct Base { Base(char* name) { } virtual ~Base(); int d; }; struct Derived : Base { Derived() : Base("someString") { } int d; void foo() { d = Base::d; } }; 

Comments

4

Use the name of the base class in an initializer-list. The initializer-list appears after the constructor signature before the method body and can be used to initialize base classes and members.

class Base { public: Base(char* name) { // ... } }; class Derived : Base { public: Derived() : Base("hello") { // ... } }; 

Or, a pattern used by some people is to define 'super' or 'base' yourself. Perhaps some of the people who favour this technique are Java developers who are moving to C++.

class Derived : Base { public: typedef Base super; Derived() : super("hello") { // ... } }; 

4 Comments

I wouldn't say that typedefing super is that common. I've never seen a project which did it, in over 20 years of C++.
@James: Agreed. There was talk on the Boost mailing list about making a small utility for having super, but nothing ever became of it. Just really isn't very useful.
I've seen it often used with the CRTP (curiously recurring template pattern) where the class you derive from is a template taking the class being defined and some other policy classes as template arguments. As the base class can end up being quite wordy with all the template arguments, it can be very handy to typedef it so you can avoid writing it out in its entire every time you want to use it. And if you want to change the base type to something that is duck-type compatible with the current base type, you can do that by changing the typedef and you don't have to change as much code.
Obviously, where multiple inheritance is involved having one name such as base or super may not be that useful, but there's plenty of code that uses single inheritance, so in practice it can be useful. I wouldn't go for the typedef solution with the simple example I posted, but when things get more involved, I think it can work out well.
1

There is no super() in C++. You have to call the Base Constructor explicitly by name.

2 Comments

You should also explain how to do it. In the code I saw today, the base class constructor was called inside the constructor of the derived class, which did nothing, except creating a temporary object of the base class.
Especially because the question was "How do I call the base class constructor?"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.