Search code examples
c++objecttypesinitializationmember

How do I declare a member object of custom type and initialize afterwards in C++?


The following code works when run at cpp.sh:

#include <iostream>

class B{
    public:
        B(int i);
        int i;
};

B::B(int i) {
    this->i = i;
}

class A{
    public:
        A(B *b);
        B *b;
};

A::A(B *b) {
    this->b = b;
}


int main()
{
  B b(8);
  A a(&b);
  std::cout << a.b->i;
}

It creates an object of type B and stores a pointer in an object of type A. What I want to do is to only pass the integer (8 in this case) and create and store the full object in a without creating an intermediate object.

But when I try to declare a object of type B (not just a pointer) inside A, I get a no matching function for call to 'B::B()error.

This is the approach I tried, which doesn't work:

#include <iostream>
// B i not changed
class B{
    public:
        B(int i);
        int i;
};

B::B(int i) {
    this->i = i;
}

class A{
    public:
        A(int i);
        B b;
};

A::A(int i) {
    this->b(i); //initialize
}


int main()
{
  A a(8);
  std::cout << a.b->i;
}

Why do I get a "no matching function" error when declaring a B b; variable instead of a pointer B *b;? Is my approach this->b(i); to initialize a member after declaration correct?


Solution

  • Your class B does not provide a constructor taking no arguments (the implicitly defined default constructor gets deleted once you declare any other constructor). When you define another class A with a data member of type class B, the system cannot initialize this data member unless you explicitly define which constructor of B with which arguments should be used.

    You can overcome this by...

    1. Call the constructor of b in an member-initializer list of A's constructor, i.e. A::A(int i) : b(i) {}

    2. Default-Initialize data member b when defining it, i.e. in A, write B b = B(1);

    3. Define a (user-defined) default constructor in B, e.g. B() : i(0) {}

    4. Define a default value in the (sole) constructor of B, e.g. B(int i=0)

    I'd prefer option 1; Options 2..4 are listed just for completeness.

    Note that any code, regardless which, in the body of a constructor is not considered as "data member initialization".