Harry Boy
Harry Boy

Reputation: 4777

Initializing a member in class constructor

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

Answers (5)

Niall
Niall

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

yu_sha
yu_sha

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

Slava
Slava

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

Quentin
Quentin

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

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

Related Questions