Home > Blockchain >  Defer calling constructor of member object declared in header until source file
Defer calling constructor of member object declared in header until source file

Time:06-08

I'd like to do declare a member object within the class declaration within my header file. I want to defer the calling of the member's constructor until the corresponding source file. This is ideally what I'd like, just for illustration:

// foo.h
class Bar(string First, string Second);
class Foo : public Base {
 public:
  Foo(int a);
  Bar  b;  // I don't want to construct here!
  ...
// foo.cc
Foo::Foo(int a)
  : base(a)
  , b("first", "second")  // <-- construct here
{}

edit: The code above is calling the "default constructor" for Bar. I get:

error: could not convert ‘{arg}’ from ‘<brace-enclosed initializer list>’ to ‘Bar’
   Bar bar;

Changing the type of b to a pointer will ripple through too many things.

Changing it to a REFERENCE is probably tenable. In the code below, since no constructor is called in the header file, that's okay for my needs!

// foo.h
class Bar;
class Foo : public Base {
 public:
  Foo(int a);
  Bar&  b;  // now it's a non-constant reference, but unassigned
  ...
// foo.cc
Foo::Foo(int a)
  : base(a)
  , b{"first", "second"}  // <-- construct here
{}

However, this results in the error: non-const lvalue reference to type 'Bar' cannot bind to an initializer list temporary. That makes sense too.

I guess I'm asking how would you do this? Is something like std::reference_wrapper going to be useful?

C 11 is a restriction.

CodePudding user response:

The constructor of a member object is called from all constructors of the containing class. That includes compiler-generated constructors.

Hence, you need to make sure that the definitions of all these constructors are in foo.cc. Now you only show Foo::Foo(int), but that's not the constructor which is causing the problem.

CodePudding user response:

I can and do include the full definition

It's exceedingly difficult to get a straight response to you so I'll go with that quote specifically and assume you meant you have a fully defined Bar type before your Foo definition.

If that's the case, your first part of the code does work as intended (once you fix the weird syntax and semantic and every other kind of errors, of course). Specifically, this works as expected:

#include <string>
using namespace std;

struct X {
    X(string a, string b) {}
};

struct Y {
    X x;
    Y() : x("a", "b") {}
};
  • Related