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. o_O
On StackOverflow, I seem to be able to find other examples of object member variables, but usually the constructor is called immediately, like this:
class MyClass {
public:
MyClass(int n);
private:
AnotherClass another(100); // this constructs AnotherClass right away!
};
But I want the MyClass
constructor to call the AnotherClass
constructor. Here's what my code looks like:
BigMommaClass.h
#include "ThingOne.h"
#include "ThingTwo.h"
class BigMommaClass {
public:
BigMommaClass(int numba1, int numba2);
private:
ThingOne* ThingOne;
ThingTwo* ThingTwo;
};
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?
I'm (also, as others mentioned) aware to the fact that this question is old, yet I wanted to point something regarding the first (and great) answer from @chris who proposed a solution to the situation where the class members are held as a "true composite" members (i.e.- NOT as pointers NOR references). The note is a bit large so I will demonstrate it here with some sample code.
When you chose to hold the members as I mentioned, you have to keep in mind also these two things:
1) For every "composed object" that DOES NOT have a default ctor - you MUST initialize it in the initialization list of ALL the ctor's of the "father" class (i.e.-
BigMommaClass
orMyClass
in the original examples andMyClass
in the code below), in case there are several (seeInnerClass1
in the example below). Meaning, you can "comment out" them_innerClass1(a)
andm_innerClass1(15)
ONLY if you enable theInnerClass1
default ctor.2) For every "composed object" that DOES have a default ctor - you MAY initialize it within the initialization list, but it will work also if you chose not to (see
InnerClass2
in the example below).See sample code (complied under Ubuntu 18.04 with
g++
version 7.3.0):I know this is 5 years later, but the replies above don't address what was wrong with your software. (Well Yuushi's does, but I didn't realise until I had typed this - doh!). They answer the question in the title How can I initialize C++ object member variables in the constructor? This is about the other questions: Am I using the right approach but the wrong syntax? Or should I be coming at this from a different direction?
Programming style is largely a matter of opinion, but an alternative view to doing as much as possible in a constructor is to keep constructors down to a bare minimum, often having a separate initialization function. There is no need to try to cram all initialization into a constructor, never mind trying to force things at times into the constructors initialization list.
So, to the point, what was wrong with your software?
Note that after these lines,
ThingOne
(andThingTwo
) now have two meanings, depending on context.Outside of BigMommaClass,
ThingOne
is the class you created with#include "ThingOne.h"
Inside BigMommaClass,
ThingOne
is a pointer.That is assuming the compiler can even make sense of the lines and doesn't get stuck in a loop thinking that
ThingOne
is a pointer to something which is itself a pointer to something which is a pointer to ...Later, when you write
bear in mind that inside of
BigMommaClass
yourThingOne
is a pointer.If you change the declarations of the pointers to include a prefix (p)
Then
ThingOne
will always refer to the class andpThingOne
to the pointer.It is then possible to rewrite
as
which corrects two problems: the double meaning problem, and the missing
new
. (You can leavethis->
if you like!) With that in place, I can add the following lines to a c++ program of mine and it compiles nicely.When you wrote
the use of
this->
tells the compiler that the left hand sideThingOne
is intended to mean the pointer. However we are insideBigMommaClass
at the time and it's not necessary. The problem is with the right hand side of the equals whereThingOne
is intended to mean the class. So another way to rectify your problems would have been to writeor simply
using
::
to change the compiler's interpretation of the identifier.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:
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.
You're trying to create a
ThingOne
by usingoperator=
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: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:Generally initializer lists are preferred for construction however, so it will look like:
You can specify how to initialize members in the member initializer list: