简体   繁体   中英

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.

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
{}

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.

"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.
};

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM