constructor


Concept: class constructors

A constructor in C++ is a special member function of a class that is automatically called when an object of that class is created. Its primary purpose is to initialize the object's data members and perform any necessary setup. Constructors have the same name as the class and do not have a return type.

Key Characteristics

Example 1: Basic Constructor

#include <iostream>
#include <string>

class Person {
private:
    std::string name;
    int age;

public:
    // Constructor
    Person(const std::string& n, int a) : name(n), age(a) {
        std::cout << "Person object created" << std::endl;
    }

    void display() const {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }
};

int main() {
    Person person1("Alice", 30);
    person1.display();

    return 0;
}

Explanation:

Example 2: Default and Parameterized Constructors

#include <iostream>
#include <string>

class Car {
private:
    std::string brand;
    std::string model;
    int year;

public:
    // Default constructor
    Car() : brand("Unknown"), model("Unknown"), year(0) {
        std::cout << "Default constructor called" << std::endl;
    }

    // Parameterized constructor
    Car(const std::string& b, const std::string& m, int y) 
        : brand(b), model(m), year(y) {
        std::cout << "Parameterized constructor called" << std::endl;
    }

    void display() const {
        std::cout << year << " " << brand << " " << model << std::endl;
    }
};

int main() {
    Car car1;  // Uses default constructor
    Car car2("Toyota", "Corolla", 2022);  // Uses parameterized constructor

    std::cout << "Car 1: ";
    car1.display();
    std::cout << "Car 2: ";
    car2.display();

    return 0;
}

Explanation:

Example 3: Constructor Overloading

#include <iostream>
#include <string>

class Rectangle {
private:
    double width;
    double height;

public:
    // Constructor with no parameters
    Rectangle() : width(1.0), height(1.0) {
        std::cout << "Default constructor called" << std::endl;
    }

    // Constructor with one parameter
    explicit Rectangle(double size) : width(size), height(size) {
        std::cout << "Single parameter constructor called" << std::endl;
    }

    // Constructor with two parameters
    Rectangle(double w, double h) : width(w), height(h) {
        std::cout << "Two parameter constructor called" << std::endl;
    }

    double area() const {
        return width * height;
    }
};

int main() {
    Rectangle rect1;
    Rectangle rect2(5.0);
    Rectangle rect3(3.0, 4.0);

    std::cout << "Area of rect1: " << rect1.area() << std::endl;
    std::cout << "Area of rect2: " << rect2.area() << std::endl;
    std::cout << "Area of rect3: " << rect3.area() << std::endl;

    return 0;
}

Explanation:

Example 4: Copy Constructor

#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int* score;

public:
    // Regular constructor
    Student(const std::string& n, int s) : name(n), score(new int(s)) {
        std::cout << "Regular constructor called" << std::endl;
    }

    // Copy constructor
    Student(const Student& other) : name(other.name), score(new int(*other.score)) {
        std::cout << "Copy constructor called" << std::endl;
    }

    // Destructor
    ~Student() {
        delete score;
    }

    void display() const {
        std::cout << "Name: " << name << ", Score: " << *score << std::endl;
    }

    void setScore(int s) {
        *score = s;
    }
};

int main() {
    Student student1("Bob", 85);
    Student student2 = student1;  // Copy constructor called

    std::cout << "Student 1: ";
    student1.display();
    std::cout << "Student 2: ";
    student2.display();

    student2.setScore(90);

    std::cout << "After changing student2's score:" << std::endl;
    std::cout << "Student 1: ";
    student1.display();
    std::cout << "Student 2: ";
    student2.display();

    return 0;
}

Explanation:

Additional Considerations

  1. Initializer Lists: Prefer using initializer lists for member initialization as they can be more efficient.

  2. Default Constructors: C++ provides a default constructor if no constructors are explicitly defined.

  3. Explicit Keyword: Use explicit for single-parameter constructors to prevent unintended implicit conversions.

  4. Delegating Constructors: In C++11 and later, constructors can call other constructors of the same class.

  5. Move Constructors: For classes managing resources, consider implementing move constructors for efficient transfers of ownership.

Summary

Constructors in C++ are essential for proper object initialization:

  1. They have the same name as the class and no return type.
  2. Can be overloaded to provide different initialization methods.
  3. Are automatically called when an object is created.
  4. Can use initializer lists for efficient member initialization.
  5. Copy constructors create new objects as copies of existing objects.

Key points to remember: - Always initialize all member variables in constructors. - Use initializer lists for better performance. - Implement copy constructors for classes with dynamically allocated resources. - Consider using explicit for single-parameter constructors to prevent implicit conversions. - Destructors should be implemented if constructors allocate resources.

Best practices: - Keep constructors simple and focused on initialization. - Use constructor overloading to provide flexibility in object creation. - Implement the Rule of Three/Five/Zero for classes managing resources. - Use default arguments in constructors when appropriate to reduce the number of overloads. - Consider using = default or = delete to explicitly control constructor generation in modern C++.

Constructors play a crucial role in C++ object-oriented programming, ensuring that objects are properly initialized and ready for use upon creation.

Related

Previous Page | Course Schedule | Course Content