Back to C++
2026-04-197 min read

Converting constructor (C++)

Learn Converting constructor (C++) step by step with clear examples and exercises.

Why This Matters

Welcome to this full guide on converting constructors in C++! This tutorial is designed to help you understand and master the art of constructor conversion, a crucial concept for both beginners and seasoned developers. Understanding constructor conversion is essential when dealing with inheritance, where the derived class may need to use the constructor of its base class. Constructor conversion allows us to create objects of derived classes using constructors from their base classes, making our code more flexible and easier to maintain.

Prerequisites

Before diving into constructor conversion, it's important that you have a solid understanding of the following topics:

  • Basic C++ syntax and programming concepts
  • Classes and objects in C++
  • Inheritance in C++
  • Access specifiers (public, private, protected)
  • User-defined constructors, constructor overloading, and constructor initialization list
  • Copy constructor and copy assignment operator
  • Exception handling (optional but recommended for understanding error cases)

Basic Concepts of Constructors

A constructor is a special member function in C++ that is used to initialize objects. When an object is created, the corresponding constructor is called automatically. Constructors have no return type, and their name must match the class name.

class MyClass {
public:
MyClass() { std::cout << "MyClass default constructor called\n"; }
};

MyClass obj; // Calls MyClass's default constructor

Constructor Overloading

Constructor overloading allows us to define multiple constructors for a single class, each with a unique parameter list. This enables us to create objects with various configurations based on the provided input.

class MyClass {
public:
MyClass() { std::cout << "MyClass default constructor called\n"; }
MyClass(int value) : _value(value) { std::cout << "MyClass constructor with int parameter called\n"; }
private:
int _value;
};

MyClass obj1; // Calls MyClass's default constructor
MyClass obj2(5); // Calls MyClass's constructor with int parameter and initializes _value to 5

Core Concept

Default Constructors and Derived Classes

When a derived class is instantiated without providing an explicit constructor call, the compiler looks for a suitable constructor in the base classes. If a default constructor exists in all base classes, the derived class will also have a default constructor that calls the default constructors of its base classes.

class Base {
public:
Base() { std::cout << "Base default constructor called\n"; }
};

class Derived : public Base {};

Derived obj; // Calls Base's default constructor

Constructor Initialization and Derived Classes

If a derived class has its own constructor, it can initialize the base class using the constructor initialization list. This allows us to control the order of construction and ensure that the base class is properly initialized before any member variables or functions are used.

class Base {
public:
Base(int value) : _value(value) { std::cout << "Base constructor called with value: " << _value << "\n"; }
private:
int _value;
};

class Derived : public Base {
public:
Derived(int baseValue, int derivedValue) : Base(baseValue), _derivedValue(derivedValue) {} // Initializing base class first
private:
int _derivedValue;
};

Derived obj(10, 20); // Calls Derived's constructor with values 10 and 20

Constructor Conversion and Derived Classes

When a derived class object is instantiated without an explicit constructor call for the derived class, the compiler looks for a suitable constructor in the base classes. If there are multiple constructors available, the compiler performs a series of conversions to find the best match. This process is known as constructor conversion.

class Base {
public:
Base(int value) : _value(value) { std::cout << "Base constructor called with value: " << _value << "\n"; }
private:
int _value;
};

class Derived : public Base {
public:
Derived(double value) : Base(static_cast<int>(value)) {} // Converting double to int for Base constructor
};

Derived obj(10.5); // Calls Derived's constructor with value 10.5, which converts to int and calls Base's constructor with value 10

Copy Constructors and Derived Classes

When a derived class object is created as a copy of another object, the compiler generates a copy constructor that performs a deep copy of all data members. If you don't provide a copy constructor for your derived class, the compiler will generate one using the copy constructors of its base classes. However, this generated copy constructor might not perform a deep copy if the base class has pointers to dynamically allocated memory.

class Base {
public:
Base(int value) : _value(new int(value)) { std::cout << "Base constructor called with value: " << *_value << "\n"; }
Base(const Base& other) : _value(new int(*other._value)) { std::cout << "Base copy constructor called\n"; }
private:
int* _value;
};

class Derived : public Base {
public:
Derived(const Base& other) : Base(other), _derivedValue(*other._derivedValue) {} // Deep copy of all data members
Derived(const Derived& other) : Base(other), _derivedValue(*other._derivedValue) { std::cout << "Derived copy constructor called\n"; }
private:
int* _derivedValue;
};

Base baseObj(10);
Derived derivedObj(baseObj); // Calls Derived's copy constructor to perform a deep copy

Worked Example

Let's create a simple Shape hierarchy with constructors for creating shapes of different types.

#include <iostream>
#include <string>

class Shape {
public:
Shape(const std::string& name) : _name(name) {} // Constructor for Shape
private:
std::string _name;
};

class Rectangle : public Shape {
public:
Rectangle(double width, double height) : Shape("Rectangle"), _width(width), _height(height) {} // Constructor for Rectangle
private:
double _width;
double _height;
};

class Circle : public Shape {
public:
Circle(double radius) : Shape("Circle"), _radius(radius) {} // Constructor for Circle
private:
double _radius;
};

int main() {
Rectangle rect(5, 3); // Creating a rectangle with width 5 and height 3
Circle circle(4); // Creating a circle with radius 4

std::cout << "Rectangle name: " << rect.getName() << "\n"; // Printing the name of rect
std::cout << "Circle name: " << circle.getName() << "\n"; // Printing the name of circle

return 0;
}

Common Mistakes

  1. Not initializing base class members in derived class constructors: If you don't initialize your base class members in the constructor initialization list, they will be left with their default values (zero for numeric types). This can lead to unexpected behavior in your program.
  1. Not providing a copy constructor or copy assignment operator for derived classes: When you create an object as a return value of a function, pass it by reference, or use it in a standard library container, the compiler will generate a default copy constructor and copy assignment operator for you. However, these generated functions may not perform deep copies (i.e., they might only copy pointers to dynamically allocated memory), leading to issues like resource leaks or inconsistent object states.
  1. Not using the initialization list for all data members: While it's not mandatory to use the initialization list for every data member, doing so can help ensure that your objects are always initialized correctly and in the order you intended.
  1. Confusing constructors with regular functions: Constructors have special properties (such as no return type) that distinguish them from regular functions. Make sure you understand these differences to avoid confusion and errors.

Practice Questions

  1. Write a constructor for a Person class that takes the person's name, age, and address as arguments. Include an overloaded constructor that initializes the person with a default name ("Unknown"), age (18), and address ("No Address Provided").
  2. Implement a copy constructor and copy assignment operator for the Person class from the previous question. Make sure they perform deep copies of all data members.
  3. Write a derived class Employee that inherits from the Person class. The Employee class should have an additional member variable salary. Include constructors for creating employees with different configurations.
  4. Create a Manager class that derives from the Employee class and adds a new member variable numOfReports. Include constructors for creating managers with different numbers of reports.
  5. Write a function displayAllEmployees(std::vector employees) that takes a vector of pointers to Employee objects and displays their names, addresses, salaries, and number of reports (if applicable).

FAQ

  1. What happens if I don't define any constructors for my class? If you don't define any constructors, the compiler will generate a default constructor for your class. This default constructor creates an object with all data members initialized to their default values (zero for numeric types and null pointers for pointer types).
  1. Can I have more than one constructor with the same name? Yes, you can overload constructors by providing different numbers or types of arguments. This allows you to create objects with various configurations based on the provided input.
  1. What is the difference between a constructor and a destructor in C++? A constructor is a special function that is called when an object is created, while a destructor is a special function that is called when an object is destroyed (either explicitly or implicitly). Constructors are used to initialize objects, while destructors are used to clean up any resources allocated by the object during its lifetime.
  1. Why do I need to define a copy constructor and copy assignment operator? When you create an object as a return value of a function, pass it by reference, or use it in a standard library container, the compiler will generate a default copy constructor and copy assignment operator for you. However, these generated functions may not perform deep copies (i.e., they might only copy pointers to dynamically allocated memory), leading to issues like resource leaks or inconsistent object states. Defining your own copy constructor and copy assignment operator ensures that your objects are always copied correctly.
Converting constructor (C++) | C++ | XQA Learn