How can I initialize C++ object member variables in the constructor?

I've got a class that has a couple of objects as member variables. I don't want the constructors for these members to be called when declared, so I'm trying to hang onto a pointer to the object explicitly. I have no idea what I'm doing.

I thought maybe I could do the following, where the constructor is called immediately when initializing the object member variable:

class MyClass {
    public:
        MyClass(int n);
    private:
        AnotherClass another(100); // Construct AnotherClass right away!
};

But I want the MyClass constructor to call the AnotherClass constructor. Here's what my code looks like:

FIle BigMommaClass.h

#include "ThingOne.h"
#include "ThingTwo.h"

class BigMommaClass {

        public:
                BigMommaClass(int numba1, int numba2);

        private:
                ThingOne* ThingOne;
                ThingTwo* ThingTwo;
};

FIle BigMommaClass.cpp

#include "BigMommaClass.h"

BigMommaClass::BigMommaClass(int numba1, int numba2) {
        this->ThingOne = ThingOne(100);
        this->ThingTwo = ThingTwo(numba1, numba2);
}

Here's the error I'm getting when I try to compile:

g++ -Wall -c -Iclasses -o objects/BigMommaClass.o classes/BigMommaClass.cpp
In file included from classes/BigMommaClass.cpp:1:0:
classes/BigMommaClass.h:12:8: error: declaration of âThingTwo* BigMommaClass::ThingTwoâ
classes/ThingTwo.h:1:11: error: changes meaning of âThingTwoâ from âclass ThingTwoâ
classes/BigMommaClass.cpp: In constructor âBigMommaClass::BigMommaClass(int, int)â:
classes/BigMommaClass.cpp:4:30: error: cannot convert âThingOneâ to âThingOne*â in assignment
classes/BigMommaClass.cpp:5:37: error: â((BigMommaClass*)this)->BigMommaClass::ThingTwoâ cannot be used as a function
make: *** [BigMommaClass.o] Error 1

Am I using the right approach, but the wrong syntax? Or should I be coming at this from a different direction?


Solution 1:

You can specify how to initialize members in the member initializer list:

BigMommaClass {
    BigMommaClass(int, int);

private:
    ThingOne thingOne;
    ThingTwo thingTwo;
};

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne(numba1 + numba2), thingTwo(numba1, numba2) {}

Solution 2:

You're trying to create a ThingOne by using operator= which isn't going to work (incorrect syntax). Also, you're using a class name as a variable name, that is, ThingOne* ThingOne. Firstly, let's fix the variable names:

private:
    ThingOne* t1;
    ThingTwo* t2;

Since these are pointers, they must point to something. If the object hasn't been constructed yet, you'll need to do so explicitly with new in your BigMommaClass constructor:

BigMommaClass::BigMommaClass(int n1, int n2)
{
    t1 = new ThingOne(100);
    t2 = new ThingTwo(n1, n2);
}

Generally initializer lists are preferred for construction however, so it will look like:

BigMommaClass::BigMommaClass(int n1, int n2)
    : t1(new ThingOne(100)), t2(new ThingTwo(n1, n2))
{ }

Solution 3:

This question is a bit old, but here's another way in C++11 of "doing more work" in the constructor before initialising your member variables:

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne([](int n1, int n2){return n1+n2;}(numba1,numba2)),
      thingTwo(numba1, numba2) {}

The lambda function above will be invoked and the result passed to thingOnes constructor. You can of course make the lambda as complex as you like.