Start learning free

LESSON 177 OF 343 · OBJECT-ORIENTED PROGRAMMING

Constructors in C++: Initializing Objects with this->

Lesson Read the full explanation

TL ; DR:

  • A constructor is a special method that runs automatically when you create an object. It's used to set up the object's initial state.


  • In C++, a constructor has the same name as the class and no return type:

    class Dog {
    public:
        string name;
        int age;
    
        Dog(string name, int age) {
            this->name = name;
            this->age = age;
        }
    };
    

  • Then create objects with arguments: Dog rex("Rex", 4); — the constructor fills in the members for you.



Full lesson:

In the previous lesson you set member variables one at a time after creating the object:

Dog dog;
dog.name = "Rex";
dog.age = 4;

That works, but it's verbose and easy to forget. Constructors let you initialize the members the moment the object is created.


Defining a constructor

A C++ constructor has two distinguishing features:

  • Its name is exactly the class name (Dog for a Dog class).

  • It has no return type — not even void.

Dog(string name, int age) {
    this->name = name;
    this->age = age;
}

The this pointer

The parameter name and the member name have the same identifier. C++ uses this->name (arrow operator, because this is a pointer) to refer to the member, and bare name for the parameter.


Calling the constructor

Dog rex("Rex", 4);
Dog luna("Luna", 7);

By the time these lines finish, rex.name is already "Rex", rex.age is 4, and the same for Luna. Note: no new is needed when creating stack-allocated objects.


Your task

The Dog class already has the name and age members. Add a constructor that takes a string name and an int age and assigns them using this->. Then in mainFunction, create two dogs:

Dog rex("Rex", 4);
Dog luna("Luna", 7);

Expected output:

Rex is 4
Luna is 7
STEP 1 OF 2
    Ctrl + Enter to check

    C++ · OBJECT-ORIENTED PROGRAMMING

    Constructors in C++, explained

    What a constructor does

    A constructor is a special member function that runs automatically when an object is created. Its job is to put the new object into a valid starting state. Without one, you create the object first and fill in its members afterwards:

    Dog dog;
    dog.name = "Rex";
    dog.age = 4;
    

    That works, but nothing forces you to do it, and a forgotten line leaves a member empty or, for an int, holding garbage. A constructor moves the setup into the class, so every object is initialized the moment it exists.

    Syntax

    A constructor differs from an ordinary member function in two ways. Its name is exactly the class name, and it has no return type, not even void.

    class Dog {
    public:
        string name;
        int age;
    
        Dog(string name, int age) {
            this->name = name;
            this->age = age;
        }
    };
    

    To call it, put the arguments in parentheses after the variable name:

    Dog rex("Rex", 4);
    Dog luna("Luna", 7);
    

    By the time each line finishes, rex.name is "Rex" and rex.age is 4. No new is needed for a stack object.

    The this pointer

    In the constructor above, the parameter name and the member name share an identifier. Inside the constructor, a bare name refers to the parameter, because the closest declaration wins. To reach the member, write this->name. Every non-static member function has a hidden pointer named this, which points at the object the function is working on. Because it is a pointer, you access members through it with the arrow operator -> rather than a dot.

    So this->name = name; reads: store the parameter name in this object's member name. If you wrote name = name; instead, you would assign the parameter to itself, and the member would stay uninitialized.

    A common alternative: the initializer list

    C++ has a second way to write the same constructor, and you will see it in most real code. The members are initialized after a colon, before the body runs:

    Dog(string name, int age) : name(name), age(age) {}
    

    Inside the parentheses, the name is the parameter; outside, it is the member, so the shadowing is not a problem here. The difference from assignment in the body is that a member in the initializer list is constructed with its value directly, instead of being default-constructed first and overwritten later. For string and int that rarely matters, but for members that can't be assigned, such as const members and references, the initializer list is the only option. This lesson uses assignments with this->, which behaves the same for these two members.

    A side effect to know about

    Once you declare any constructor, the compiler stops generating the default one that takes no arguments. After this lesson's change, the line Dog d; no longer compiles, because every Dog must now be created with a name and an age. GCC reports no matching function for call to 'Dog::Dog()'. If you also want objects with no arguments, add a second constructor with no parameters.

    The lesson's exercise

    The Dog class has the members name and age. There are two steps:

    1. Under public: inside Dog, add a constructor Dog(string name, int age) whose body assigns the parameters to the members with this->. It has to be public, because code outside the class creates the dogs.
    2. In mainFunction, create rex and luna with the arguments "Rex", 4 and "Luna", 7. They must come before the cout lines that use them.

    The expected output is:

    Rex is 4
    Luna is 7

    The solution in C++

    class Dog {
    public:
        string name;
        int age;
    
        Dog(string name, int age) {
            this->name = name;
            this->age = age;
        }
    };
    
    class Solution {
    public:
        void mainFunction() {
            Dog rex("Rex", 4);
            Dog luna("Luna", 7);
            cout << rex.name << " is " << rex.age << endl;
            cout << luna.name << " is " << luna.age << endl;
        }
    };
    

    The arguments are matched to the parameters by position, so "Rex" becomes name and 4 becomes age. Swapping them is a compile error here, since a number can't become a string that way.

    Common mistakes

    • Adding a return type. void Dog(string name, int age) is rejected by the compiler, because a function named like its class is a constructor and can't have a return type.
    • Writing name = name; without this->. The parameter is assigned to itself and the member keeps its old value.
    • Placing the constructor under private:. Code outside the class then can't create objects.
    • Using this.name. this is a pointer, so use this->name.
    • Creating an object without arguments after defining only this constructor.
    • Using empty parentheses for a no-argument call. Dog d(); declares a function. Write Dog d; instead.

    Key takeaways

    • A constructor has the class's name and no return type, and it runs when the object is created.
    • Pass the arguments after the variable name: Dog rex("Rex", 4);.
    • this->name is the member; a bare name is the parameter when they share a name.
    • An initializer list (: name(name), age(age)) is the idiomatic alternative.
    • Declaring a constructor removes the automatic no-argument one.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free