Constructors in C++
Constructors are an essential component of C++ that regulate the creation and initialization of objects, which is vital to Object-Oriented Programming (OOP).
Role and Definition of Constructors
One of a class’s unique member functions is a constructor. Initialization of its class’s objects is its main responsibility. When an object of its associated class is created or defined, constructors are immediately called. This automatic invocation helps to avoid runtime issues that could result from uninitialized data by ensuring that an object will be initialized upon creation.
Characteristics of constructors
The following are important traits of constructors:
- Naming Convention: The class name that a constructor belongs to and its name must match perfectly.
- No Return Type: There is no return type not even void for constructors, in contrast to other methods. The reason for this is that the system calls them automatically and there isn’t a program to return a value to.
- Parameters: Constructors that are parameterized are able to take parameters. These parameters give the object’s data members their initial values.
- Overloading: Class constructors might differ in parameter number or type. This enables alternative approaches to object initialization according to distinct requirements.
- const restriction: Declaring constructors as const is not possible. Since the constructor can write to const objects while they are being constructed, the object’s “constness” only becomes effective once its initialization is finished.
- Default Constructor: By default, a constructor is one that can be called without any arguments. A default constructor is frequently implicitly defined by the compiler if you create additional constructors for a class but not explicitly. Writing = default after the definition of the default constructor in C++11 and later allows you to specifically request that the compiler generate it.
- Establishing Invariants: In order to create a class invariant a requirement that must always be met anytime a member function is invoked from outside the class constructors are necessary.
- Copy Control: A broader group of special member functions, such as the copy and move constructors, are included in constructors and govern the copying and moving of objects.
Constructor Initializer Lists
A constructor initializer list, also called a member initialization list, is required for initializing data members in constructor specifications.
- Syntax: The initializer list is separated by a colon (:) from the constructor’s argument list, whereas the function body (curly braces {}) comes first. The initial value of each member is followed by their name in curly brackets or brackets. Commas are used to join multiple initialisations.
- Initialization vs. Assignment: Initializer lists are important because they initialize members before the constructor body starts running. If a member is not initialized in the initializer list, the constructor body defaults it. Initializer lists are usually utilized because they are faster than assigning values in the constructor body.
- Required Initialization: Class type members without a default constructor, reference data members, and const data members must all be initialized with a constructor initializer list. An error will occur at compilation time if these types are not initialized in the list.
- Order of Initialization: One possibly unexpected rule is that members are initialized not in the order they appear in the initializer list but rather in the order they are defined in the class definition. In order to avoid misunderstandings and possible problems, initializers should be listed in the same sequence as member declarations.
- Delegating Constructors: Delegating constructors in C++11 allow one constructor to call another from the same class using an initializer list. Code becomes less repetitious and manageable.
Code Example: Illustrating Constructors and Initializer Lists
#include <iostream> // For input/output operations like std::cout and std::endl
#include <string> // For using std::string to store text
// Define a class named 'Book'
class Book {
private:
// Private data members (attributes of a book)
std::string title;
std::string author;
int publicationYear;
double price;
public:
// 1. Default Constructor
// Initializes all data members to default values using an initializer list.
// This constructor is called when a 'Book' object is created without arguments.
Book() : title("Unknown"), author("Unknown"), publicationYear(2000), price(0.0) {
std::cout << "Default constructor called (No arguments)." << std::endl;
}
// 2. Parameterized Constructor using Constructor Initializer List
// This constructor takes arguments for all data members and uses the initializer
// list to directly initialize them. This is the preferred way to initialize.
Book(std::string t, std::string a, int year, double p)
: title(t), // Initializes 'title' with 't'
author(a), // Initializes 'author' with 'a'
publicationYear(year), // Initializes 'publicationYear' with 'year'
price(p) // Initializes 'price' with 'p'
{
std::cout << "Parameterized constructor called (All arguments)." << std::endl;
// The constructor body remains empty as all initialization is done in the list.
}
// 3. Another Parameterized Constructor (Demonstrates Constructor Overloading)
// This constructor takes only title and author, and sets default values for year and price.
// It also uses an initializer list to ensure proper initialization order and efficiency.
Book(std::string t, std::string a)
: title(t), author(a), publicationYear(2023), price(29.99)
{
std::cout << "Two-argument constructor called (Title and Author)." << std::endl;
}
// Public member function to display book information (accessor)
void displayBookInfo() const {
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << author << std::endl;
std::cout << "Year: " << publicationYear << std::endl;
std::cout << "Price: $" << price << std::endl;
}
};
int main() {
std::cout << "--- Creating book1 (using default constructor) ---" << std::endl;
Book book1; // Creates an object using the default constructor
book1.displayBookInfo();
std::cout << std::endl;
std::cout << "--- Creating book2 (using full parameterized constructor) ---" << std::endl;
Book book2("The C++ Programming Language", "Bjarne Stroustrup", 2013, 75.50); // Calls the constructor with all parameters
book2.displayBookInfo();
std::cout << std::endl;
std::cout << "--- Creating book3 (using two-argument constructor) ---" << std::endl;
Book book3("Effective C++", "Scott Meyers"); // Calls the overloaded constructor with two parameters
book3.displayBookInfo();
std::cout << std::endl;
return 0;
}
Output
--- Creating book1 (using default constructor) ---
Default constructor called (No arguments).
Title: Unknown
Author: Unknown
Year: 2000
Price: $0
--- Creating book2 (using full parameterized constructor) ---
Parameterized constructor called (All arguments).
Title: The C++ Programming Language
Author: Bjarne Stroustrup
Year: 2013
Price: $75.5
--- Creating book3 (using two-argument constructor) ---
Two-argument constructor called (Title and Author).
Title: Effective C++
Author: Scott Meyers
Year: 2023
Price: $29.99
You can also read What Are The Accessing Members In C++ With Code Example