Question
In C++, what are the rules for calling a base class constructor from a derived class?
For example, in Java, the base constructor must be called as the first line of the subclass constructor. If you do not call it explicitly, Java inserts an implicit call to the no-argument super() constructor, which causes a compile error if that constructor does not exist.
How does this work in C++?
Short Answer
By the end of this page, you will understand how C++ constructs base classes from derived classes, when a base constructor is called automatically, how to explicitly choose which base constructor to call, and what order constructors run in. You will also see common mistakes and how this differs from Java.
Concept
In C++, a derived object is built in layers.
When you create an object of a derived class, C++ first constructs its base class subobject, then constructs the derived class's own members and body. This happens automatically as part of object construction.
The important rule is:
- Base class constructors are called before the derived class constructor body runs.
- You do not call the base constructor inside the body like a normal function.
- Instead, you choose the base constructor in the derived constructor's member initializer list.
Basic idea
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived(int x) : Base(x) {}
};
Here, Base(x) is not a normal function call. It tells C++ which Base constructor should be used before Derived is finished being constructed.
If you do not specify a base constructor
If the derived constructor does not mention the base class in the initializer list, C++ tries to call the base class's default constructor.
class Base {
public:
Base() {}
};
class Derived : public Base {
public:
Derived() {}
};
This works because Base() exists.
But if the base class has no default constructor, the code fails:
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived() {}
};
This is an error because C++ tries to call Base() automatically, but Base() does not exist.
Why this matters
This rule matters because construction is about guaranteeing that every part of an object is valid before you use it. A derived class depends on its base class already being properly initialized. That is why C++ forces base construction to happen first.
This also affects:
- classes with constructor parameters
- classes with
constmembers or reference members - inheritance hierarchies in real applications
- resource management patterns such as RAII
Mental Model
Think of a derived object like building a house on top of a foundation.
- The base class is the foundation.
- The derived class is the upper structure.
You cannot build the upper floor first and then decide what kind of foundation you wanted. The foundation must be poured first.
In C++, the member initializer list is where you tell the builder which foundation to use.
Derived(int x) : Base(x) {}
That means: "Before building the Derived part, first construct the Base part with x."
The constructor body runs only after that foundation already exists.
Syntax and Examples
Core syntax
Use the base class constructor in the derived constructor's initializer list:
class Base {
public:
Base(int value) {}
};
class Derived : public Base {
public:
Derived(int value) : Base(value) {}
};
Example 1: Explicitly calling a base constructor
#include <iostream>
using namespace std;
class Animal {
public:
Animal(string name) {
cout << "Animal constructed: " << name << endl;
}
};
class Dog : public Animal {
public:
Dog(string name) : Animal(name) {
cout << "Dog constructed" << endl;
}
};
int main() {
Dog d("Rex");
}
What this does
Dog("Rex")starts constructing aDogobject.- Before
Dog's constructor body runs,Animal(name)runs. - After the base class is ready, the
Dogconstructor body runs.
Output
Animal constructed: Rex
Dog constructed
Example 2: Default base constructor used automatically
#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "Base default constructor" << endl;
}
};
class Derived : public Base {
public:
Derived() {
cout << "Derived constructor" << endl;
}
};
int main() {
Derived d;
}
Output
Base default constructor
Derived constructor
Because Derived() does not specify a base constructor, C++ uses Base() automatically.
Example 3: Compile error when no default base constructor exists
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived() {}
};
This fails because C++ tries to call Base() automatically, but only Base(int) exists.
Step by Step Execution
Consider this example:
#include <iostream>
using namespace std;
class Base {
public:
Base(int x) {
cout << "Base: " << x << endl;
}
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x) {
cout << "Derived: " << y << endl;
}
};
int main() {
Derived obj(10, 20);
}
Step-by-step
main()createsobjwithDerived obj(10, 20);- C++ starts constructing a
Derivedobject. - Before entering the
Derivedconstructor body, it sees: Base(x)in the initializer list. Base(10)runs first.- It prints:
Base: 10
- Now the base part of the object is fully constructed.
- C++ enters the
Derivedconstructor body. - It prints:
Derived: 20
Final output
Base: 10
Derived: 20
Key takeaway
Even though the Derived constructor appears in your code, the base constructor always runs first. The initializer list selects the base constructor, and the body runs afterward.
Real World Use Cases
Base constructor calls appear often in real C++ programs.
1. Initializing shared state in a framework base class
A base class may store common data such as an ID, name, file path, or configuration.
class Widget {
public:
Widget(string id) {}
};
class Button : public Widget {
public:
Button(string id) : Widget(id) {}
};
2. Resource management
A base class may open or manage a resource during construction.
class FileOwner {
public:
FileOwner(const string& path) {}
};
class LogFile : public FileOwner {
public:
LogFile(const string& path) : FileOwner(path) {}
};
3. Reusing validation or setup logic
A base class can ensure core invariants are established before the derived class adds extra behavior.
4. GUI, game, and engine code
Frameworks often have base classes like Entity, Component, or Window. Derived classes pass values up to the base constructor so the framework can initialize common behavior first.
5. API and server code
Controllers, handlers, or service classes may inherit from a base type that stores dependencies, environment settings, or shared metadata.
Real Codebase Usage
In real codebases, developers usually combine base constructor calls with a few common patterns.
Guarding object validity early
The base class often establishes state that every derived object must have.
class Connection {
public:
Connection(string host) {
// validate or store host
}
};
class SecureConnection : public Connection {
public:
SecureConnection(string host) : Connection(host) {}
};
Forwarding constructor arguments
A common pattern is to receive arguments in the derived constructor and pass some or all of them to the base constructor.
class Person {
public:
Person(string name) {}
};
class Employee : public Person {
public:
Employee(string name, int id) : Person(name), employeeId(id) {}
private:
int employeeId;
};
Initializing members and base classes together
Initializer lists are used not just for base classes, but also for members.
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x), value(y) {}
private:
int value;
};
Constructor delegation is different
You cannot initialize a base class later from inside the constructor body. It must happen during construction.
Error handling
If base construction fails by throwing an exception, the derived constructor body never runs. This is important in code that manages files, sockets, memory, or locks.
Common Mistakes
1. Trying to call the base constructor inside the constructor body
This is wrong:
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived(int x) {
Base(x); // does not initialize the base subobject
}
};
Why it is wrong:
- The base subobject has already been constructed before the body starts.
Base(x);inside the body creates a temporary object instead of initializing the inherited base part.
Correct version:
class Derived : public Base {
public:
Derived(int x) : Base(x) {}
};
2. Forgetting that C++ uses the default base constructor automatically
Broken code:
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived() {}
};
Problem:
- C++ tries
Base()automatically. - But
Base()does not exist.
Fix:
class Derived : public Base {
public:
Derived() : Base(0) {}
};
3. Assuming initializer list order controls construction order
class Base1 {
public:
Base1() {}
};
class Base2 {
public:
Base2() {}
};
class Derived : public Base1, public Base2 {
public:
Derived() : Base2(), Base1() {}
};
Many beginners think Base2 will be constructed first because it appears first in the initializer list. That is false.
Construction order follows the class declaration order:
class Derived : public Base1, public Base2
So Base1 is constructed before Base2.
4. Forgetting member initialization also happens before the body
Members, like base classes, should usually be initialized in the initializer list rather than assigned in the body.
5. Expecting Java-style syntax
In Java, super(...) appears in the constructor. In C++, the equivalent is the initializer list syntax:
Derived(int x) : Base(x) {}
Comparisons
C++ vs Java base constructor rules
| Topic | C++ | Java |
|---|---|---|
| Where base constructor is specified | In the initializer list | In the constructor using super(...) |
| Must base construction happen before derived body? | Yes | Yes |
| Automatic call if omitted | Yes, tries the base default constructor | Yes, inserts super() |
| Error if no default constructor exists | Yes | Yes |
| Can you call base constructor in body? | No | No |
| Syntax style | Derived() : Base(args) {} | Derived() { super(args); } |
Initializer list vs constructor body
| Approach | Use case | Important note |
|---|---|---|
| Initializer list | Initialize base classes and members | Runs before constructor body |
| Constructor body | Additional logic after initialization | Too late for base construction |
Explicit base constructor vs implicit default constructor
| Situation | Result |
|---|---|
Derived() : Base(5) {} | Calls Base(int) |
Derived() {} and Base() exists | Calls Base() automatically |
Derived() {} and Base() does not exist | Compile error |
Cheat Sheet
Quick rules
- A base class is constructed before the derived class body runs.
- Use the initializer list to choose the base constructor.
- Syntax:
Derived(args) : Base(baseArgs) {}
- If you omit the base constructor, C++ tries to call the base default constructor.
- If no default constructor exists, compilation fails.
- You cannot initialize the base class from inside the constructor body.
- Base classes are constructed before members.
- With multiple base classes, construction order follows the inheritance declaration order, not the initializer list order.
Common pattern
class Base {
public:
Base(int x) {}
};
class Derived : public Base {
public:
Derived(int x, int y) : Base(x), value(y) {}
private:
int value;
};
Wrong pattern
Derived(int x) {
Base(x); // wrong: temporary object, not base initialization
}
Remember
- Initialization happens first.
- Constructor body happens second.
FAQ
What happens if I do not call the base class constructor in C++?
C++ automatically tries to call the base class default constructor. If the base class has no default constructor, compilation fails.
Can I call the base constructor from inside the derived constructor body?
No. By the time the body runs, the base part has already been constructed. You must use the initializer list.
Is Base(x) inside the initializer list a normal function call?
No. It is constructor initialization syntax, not a regular function call.
In what order are constructors called in inheritance?
Base class constructors run first, then member objects, then the derived constructor body.
What if there are multiple base classes?
They are constructed in the order they appear in the class inheritance declaration, not the order written in the initializer list.
Is C++ behavior similar to Java super()?
Yes in purpose, but the syntax is different. C++ uses the initializer list, while Java uses super(...) inside the constructor.
What if the base constructor throws an exception?
The derived constructor body will not run, because the object was not fully constructed.
Do I always need to write the base constructor explicitly?
No. Only when you want a specific base constructor or when the base has no usable default constructor.
Mini Project
Description
Build a small inheritance example that models a user account system. The base class should store a username, and the derived class should add a permission level. This demonstrates how a derived class passes required data to the base constructor during object creation.
Goal
Create a derived object that correctly initializes both the base class and its own member data using a constructor initializer list.
Requirements
- Create a base class named
Userwith a constructor that requires a username. - Create a derived class named
AdminUserthat inherits fromUser. - Pass the username from
AdminUserto theUserconstructor. - Store a permission level inside
AdminUser. - Print both the username and permission level to confirm construction worked.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.