Question
In C#, it is common to chain constructors so that one constructor reuses the work of another. For example:
class Test {
public Test() {
DoSomething();
}
public Test(int count) : this() {
DoSomethingWithCount(count);
}
public Test(int count, string name) : this(count) {
DoSomethingWithName(name);
}
}
Is there an equivalent way to do this in C++?
I tried calling the class name directly and also tried using the this keyword inside a constructor, but neither approach worked.
Short Answer
By the end of this page, you will understand how constructor chaining works in C++, when it is supported, and how to share initialization logic safely. You will learn about delegating constructors, initializer lists, older workarounds used before modern C++, and common mistakes beginners make when trying to call one constructor from another.
Concept
In C++, constructor chaining is usually called delegating constructors.
A delegating constructor is a constructor that forwards construction to another constructor in the same class.
In modern C++ (C++11 and later), this is supported directly:
class Test {
public:
Test() {
DoSomething();
}
Test(int count) : Test() {
DoSomethingWithCount(count);
}
Test(int count, const std::string& name) : Test(count) {
DoSomethingWithName(name);
}
private:
void DoSomething() {}
void DoSomethingWithCount(int) {}
void DoSomethingWithName(const std::string&) {}
};
This is the C++ equivalent of C# constructor chaining.
Why this matters
Constructors often need to do shared setup:
- initialize member variables
- validate input
- open resources
- avoid duplicated code
Mental Model
Think of constructing a C++ object like assembling a machine at a factory.
- A constructor is the assembly process.
- A delegating constructor says: "Start with the basic assembly process first, then add extra parts."
- A failed attempt like calling
Test()inside another constructor is like accidentally building a different machine on the side, not continuing work on the current one.
So in C++:
Test() : Test(other)means build this object by first using another constructor.Test();inside the constructor body means make a temporary separate object.
That difference is one of the most important ideas to remember.
Syntax and Examples
Core syntax
In C++11 and later, you delegate to another constructor in the member initializer list:
ClassName(parameters) : ClassName(other_arguments) {
// extra work here
}
Example
#include <iostream>
#include <string>
class Test {
public:
Test() {
std::cout << "Base setup\n";
}
Test(int count) : Test() {
std::cout << "Count: " << count << "\n";
}
Test(int count, const std::string& name) : Test(count) {
std::cout << "Name: " << name << "\n";
}
};
int main() {
Test a;
std::cout << "---\n";
Test b(3);
std::cout << "---\n";
Test ;
}
Step by Step Execution
Consider this example:
#include <iostream>
#include <string>
class Test {
public:
Test() {
std::cout << "1. Default constructor\n";
}
Test(int count) : Test() {
std::cout << "2. Count constructor: " << count << "\n";
}
Test(int count, const std::string& name) : Test(count) {
std::cout << "3. Name constructor: " << name << "\n";
}
};
int main() {
Test t(10, "Sam");
}
What happens?
When this line runs:
Test t(10, "Sam");
C++ follows these steps:
- It chooses the constructor .
Real World Use Cases
Constructor chaining is useful whenever objects have multiple ways to be created but still need common setup.
Common examples
Configuration objects
class Config {
public:
Config() : host("localhost"), port(8080) {}
Config(int p) : Config() { port = p; }
private:
std::string host;
int port;
};
Use case:
- default development settings
- allow overriding only one value
File or resource wrappers
A class might always need base validation or default state before opening a file with different options.
Logging classes
A logger may always initialize a default log level, while other constructors add file names, prefixes, or formatting options.
API clients
An HTTP client may start with default headers and timeout values, while additional constructors supply a token, base URL, or retry settings.
Game objects or UI components
Objects may always need default position, ID, or style settings, while overloaded constructors customize size, label, or behavior.
Real Codebase Usage
In real projects, developers use constructor chaining to keep initialization consistent and avoid copy-paste logic.
Common patterns
1. Default values plus overrides
A base constructor sets safe defaults, and other constructors override only what changes.
class ServerOptions {
public:
ServerOptions() : port(80), useSsl(false) {}
ServerOptions(int p) : ServerOptions() { port = p; }
ServerOptions(int p, bool ssl) : ServerOptions(p) { useSsl = ssl; }
private:
int port;
bool useSsl;
};
2. Input validation in one place
One constructor can normalize or validate values before shared state is used.
3. Guarding against duplication
Instead of repeating the same setup in several constructors, delegate to a single constructor that owns the common initialization.
4. Combining with initializer lists
In C++, member initialization should usually happen in initializer lists, not by assigning inside the constructor body.
class User {
:
() : (), () {}
( std::string& n) : () { name = n; }
:
std::string name;
age;
};
Common Mistakes
1. Calling the constructor like a normal function
Broken example:
class Test {
public:
Test() {}
Test(int count) {
Test(); // wrong
}
};
Problem
This creates a temporary Test object. It does not initialize the current object.
Fix
Use delegation in the initializer list:
class Test {
public:
Test() {}
Test(int count) : Test() {}
};
2. Trying to use this() like in C#
Broken example:
class Test {
public:
Test() {}
Test(int count) : this() { // wrong
}
};
Problem
Comparisons
| Concept | C# | C++ |
|---|---|---|
| Constructor chaining syntax | : this(...) | : ClassName(...) |
| Where chaining happens | Constructor initializer | Member initializer list |
| Can constructor be called in body to reinitialize same object? | No | No |
| Calling class name in constructor body | Not used for chaining | Creates a temporary object |
| Language support | Built in | Built in from C++11 |
Delegating constructor vs helper function
| Approach | Best for | Drawback |
|---|---|---|
Cheat Sheet
Constructor chaining in C++
Modern syntax
class Test {
public:
Test() {}
Test(int x) : Test() {}
Test(int x, const std::string& name) : Test(x) {}
};
Rules
- Use
: ClassName(...)to delegate. - Delegation happens in the initializer list.
- Only one constructor runs first as the target.
- Add extra work in the constructor body after delegation.
- Requires C++11 or later.
Do not do this
Test() ; // declaration, not chaining
Test(); // creates a temporary object in a constructor body
this->Test(); // invalid
:this(); // C# style, not C++
Best practices
- Put common setup in one constructor.
- Prefer initializer lists for member initialization.
- Avoid duplicated constructor logic.
- Avoid cyclic delegation.
Pre-C++11 fallback
FAQ
Can I call one constructor from another in C++?
Yes, in C++11 and later you can use delegating constructors with the syntax : ClassName(...).
Why does calling Test() inside a constructor not work?
Because it creates a separate temporary object instead of reusing the current object.
Is this() valid in C++ like it is in C#?
No. C++ constructor delegation uses the class name, not this().
Do delegating constructors work in old C++ versions?
No. They were added in C++11. In older code, use a helper function or redesign the constructors.
Should I use a helper function instead of constructor chaining?
Use a helper function only when delegating constructors are unavailable or when the shared code is not true initialization logic.
Can constructor delegation be recursive?
No. Cyclic delegation is invalid and must be avoided.
Should I initialize members in the body or the initializer list?
Prefer the initializer list whenever possible. It is usually more efficient and idiomatic in C++.
Mini Project
Description
Build a small DatabaseConfig class that supports several ways of creating configuration objects while sharing common setup. This demonstrates constructor chaining in a realistic scenario: default values, partial customization, and full customization.
Goal
Create a class that provides sensible defaults and allows more specific constructors to reuse earlier initialization logic.
Requirements
- Create a
DatabaseConfigclass withhost,port, anduseSslfields. - Provide a default constructor that sets sensible default values.
- Provide a constructor that changes only the port.
- Provide a constructor that changes both host and port.
- Provide a constructor that changes host, port, and SSL setting using constructor delegation.
Keep learning
Related questions
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++ Base Class Constructor Rules Explained
Learn how C++ base class constructors are called from derived classes, including order, syntax, defaults, and common mistakes.
C++ Casts Explained: C-Style Cast vs static_cast vs dynamic_cast
Learn the difference between C-style casts, static_cast, and dynamic_cast in C++ with clear examples, safety rules, and real usage tips.