Reputation: 4777
Can someone explain why I cannot initialise a variable in the body of the constructor in the same way as I can do it in the member initialisation list.
class MyClass
{
public:
MyClass();
virtual ~MyClass(void);
private:
std::string test;
};
MyClass::MyClass()
: test("asdf") <-- Case 1: This is OK
{
test("asdf"); <-- Case 2: This is not
}
I'm asking as I have a 3rd party class that I need to use and initialize by passing certain variables into its constructor. It is fine if I use it as in Case 1 above but not as in Case 2.
Upvotes: 4
Views: 13419
Reputation: 30614
The syntax varies between constructing an object in the member initialisation list and assigning it a value in the body of the constructor.
In the initialisation list, it is as you have it;
MyClass::MyClass()
:test("abcd")
{
//...
}
In the body, you can use the assignment syntax
test = "abcd";
The syntax test("asdf");
is parsed as a function called test
that is being called with a argument of "abcd"
.
It must be borne in mind that if the member does not have a default constructor, the initialisation list is the only place to correctly construct the member. Once the body of the constructor runs, all the member have been constructed or initialised in some manner. They may be assigned to, if possible (e.g. not applicable to references and const
members etc.), but not reconstructed.
Upvotes: 10
Reputation: 4400
test("asdf") is a function call and you cannot call strings like that. Initialization list ("Case 1") is a special case.
In the constructor body, just use assignment
test="asdf".
In this case, at first string test is default-constructed (becomes empty) and then a new string gets constructed and assigned to member test.
Upvotes: 1
Reputation: 44268
You cannot initialize member in constructor body because it is already initialized at that point and syntax reflect that fact. That is already answered but I would like to point to another thing - improperly using terminology may lead to incorrect code. So some people say "you may initialize in constructor body by assignment". Why is this wrong? Let's look into this example:
struct foo {
int i = 0;
int &r = i;
foo() {}
foo( int &ref );
};
and you want r
point to the same as ref
if that ctor is called:
foo::foo( int &ref ) : r( ref )
{
}
now what will happen if you try to "initialize" by assignment:
foo::foo( int &ref )
{
r = ref;
}
so now instead of pointing int
reference r
to the same int
as ref
you just assigned value to member i
. This may lead to difficult to catch bugs and morale is: "terminology is important in programming, and you should not freely play with it"
Upvotes: 1
Reputation: 63154
You cannot initialize a variable in the constructor's body, because the constructor's body runs after all base classes and members have already been initialized in the member initialization list. That they are implicitly default-initialized because you didn't list them there is irrelevant.
So, in the body, test("asdf");
tries to call operator()
on test
, which fails. Use assignment (test = "asdf";
) to change its value, or better yet initialize it directly in the member initialization list.
Upvotes: 6
Reputation: 4131
You have bellow ways to initialize variables in constructors :
class MyClass
{
public:
MyClass();
virtual ~MyClass(void);
private:
std::string test;
};
way 1 :
MyClass::MyClass() : test("asdf")
{
}
way 2 :
MyClass::MyClass()
{
test = "asdf";
}
Upvotes: 1