CXJ
CXJ

Reputation: 4459

C++ How to Initialize member object?

Is there some way to initialize(?) member variable c of type C in the first part of the below example? Or must I use the new() method shown in the second part of the example?

Class B takes class A as an injected dependency. So does class C. Class B is additionally composed of class C.

How do I get the injected A to B's member C?

Part 1

class A { // ...; };

class C {
public:
    C(A &a) : a(a) {}   // constructor
};


// Does not work as is.  Want to make compiler manage C lifetime.
class B {
public:
    B(A &a);    // constructor

    C c(a);     // member variable
};

// constructor
B::B(A &a) : a(a) {
}

Part 2

// Works, but requires programmer to manage C's lifetime.
class B {
public:
    B(A &a);    // constructor

    C *c;       // member variable
};

// constructor
B::B(A &a) : a(a) {
    c = new C(a);
}

Several good answers below! My apologies for the confusing example. I have up-voted all of the good answers and questions. Unfortunately I can only mark one answer as the accepted answer, so I am choosing the first one which gave me the "ah-ha" moment in which I saw the solution to my real problem, which was more complex than my lame example here.

Upvotes: 0

Views: 3917

Answers (4)

Emil Laine
Emil Laine

Reputation: 42838

The following:

C(A &a) : a(a) {}

will not compile since a (the first a in the initialization list) is not a member variable of C.

Same applies to the constructor of B.

Upvotes: 1

Qaz
Qaz

Reputation: 61910

You almost have it:

class B {
public:
    B(A &a);

    C c(a); //see note 1
};

B::B(A &a) : a(a) { //see note 2
}

Note 1:

There are two problems with C c(a); here:

  1. a is not in scope. a only exists within the scope of the constructor, so c needs to be initialized from there.
  2. Until C++11, non-static data member initializers (NSDMIs) were prohibited. Even in C++11, though, you must use an equals sign (C c = value;) or braces (C c{value};) when initializing an NSDMI.

Note 2:

You've almost got this right:

B::B(A &a) : a(a)

You're trying to initialize a data member called a with the argument given to the constructor. You actually want to initialize c like this, not a non-existent a:

B::B(A &a) : c(a)

The lifetime of c will be that of the instance of the B class. Using dynamic memory management is certainly not necessary.

Upvotes: 3

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

"How do I get the injected A to B's member C?"

You can do so using B's constructor member initializer list

class B {
public:
    B(A &a) : c(a) {
           // ^^^^
    }

    C c; // <<< It's not possible to initialize members in their
         //     declaration.
};

Upvotes: 1

StenSoft
StenSoft

Reputation: 9609

Member variables are initialized in constructor's initialization list (before body) so you need to do that:

B::B(A &a)
    : c(a) // Calls constructor C(a) on member c
{}

Upvotes: 3

Related Questions