0

I am writing code that follows the member dependency schemes discussed in:

Resolve build errors due to circular dependency amongst classes

In it's simplest form, the code headers looks like this:

A.h

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

B.h

#include A.h
#include foo.h

class B : public foo{

 public:
  B(A *a);
  A *a;
  void send(int i); //this invokes a member function of a
};

Now, in my source code, if I use an initializer list that looks like:

A.cpp

A::A() : b(this){};

I get a compiler error saying "error: cannot convert ‘A* const’ to ‘B*’ in initialization

However, if I don't use an initializer list, and instead I use a new pointer declaration, it compiles fine:

A::A(){
b = new B(this);
}

Could anyone help me reason why the initializer list causes the compiler to misinterpret the class B constructor argument? Or maybe something else is happening?

Just in case it helps, here is the B.cpp file:

B.cpp

#include "B.h"
#include "A.h"

B::B(A *inst){
    a = inst;
}

void B::send(int i){
    a->send(i);
}
  • `this` in the constructor of A will refer to the instance of A, not an instance of B, hence the error. You still have to create the instance of B. – fredrik Dec 02 '20 at 17:12

2 Answers2

1

In your assignment:

b = new B(this);

you are constructing a B object from this, and assigning a pointer to this object to b. You need to do the same thing in your member initializer list:

A::A() : b(new B{this}){};
cigien
  • 57,834
  • 11
  • 73
  • 112
0

First, let's remove the noise and minimize your example:

struct A;
struct B { B(A*) {} };

struct A {
    A() : b(this) { }; // error: cannot convert 'A*' to 'B*' in initialization
    B* b;
};

int main() {}

The data member b of A is of of type B* rather than B, and we can minimize the example even further:

struct A {};
struct B { B(A*) {} };

int main() {
    A a{};
    A* pa = &a;
    B* pb{pa};  // error: cannot convert 'A*' to 'B*' in initialization
}

The error message is now quite explanatory (given the simple context): we simply cannot

  • initialize a pointer to B by a pointer to A.

The constructor of B is not relevant here, as it provides a way to:

  • initialize an object of type B by a pointer to A.

The new operator, however, dynamically creates object and returns a pointer to it, meaning that the following:

B* pa{new B(pa)};

is:

  • initializing a pointer to B by a pointer to B which points to an object of type B which was initialized by a pointer to A.
dfrib
  • 70,367
  • 12
  • 127
  • 192