Problem Summary
I'm attempting to write a series of classes in C 14, that are all supposed to be inside of the same class, and have pointer fields that point to object instances of each one of the classes. They are all also supposed to have constructors that assign those fields, using arguments that are pointers to the other class instances. I'm running into a problem where I am unable to call the constructor with the pointer arguments. Below is an illustration of my problem:
Defined in header file:
class A;
class B;
class C;
class A {
public:
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
Runner code in cpp file:
A::C TEST_C = *new A::C();
A::B TEST_B = *new A::B(&TEST_C);
The line which initializes TEST_B
with the constructor pointer argument call gives the following two errors in the VS 2019 compiler:
Error C2664 'A::B::B(C *)': cannot convert argument 1 from 'A::C *' to 'C *'
Error C2512 'A::B': no appropriate default constructor available
My Attempts
The first error line got me thinking that I may need to change my forward class declarations to include their respective parent classes too, as such:
class A;
class A::B;
class A::C;
However, that appears to break the reference to class C
completely, and any references to it in the header above it's definition treat it as an undefined reference (Identifier "C" is undefined.
). It's as if there were no forward declarations at all.
Adding A::
to each reference to class C
in the rest of the header as such:
class A {
public:
class B {
public:
B(A::C* arg) {
ptr = arg;
}
A::C* ptr;
};
class C {
public:
...
};
};
didn't help either, instead the compiler tells me Class "A" has no member "C".
.
However, one interesting thing that I did notice, was the fact that if I change the argument being passed to the constructor call for class B
, to nullptr
, that is:
A::B TEST_B = *new A::B(nullptr);
then the code gets compiled without problems. To me, that meant that this is most likely an issue with my forward class declarations, where the compiler sees that there are classes B
and C
declared, but it doesn't get to reading the actual content of the classes prior to attempting to reference them.
Is what I'm trying to accomplish here even possible with C ? Is there a way I should be doing this properly, that I'm not seeing?
Thank you in advance for reading my post, any help is appreciated!
CodePudding user response:
The problem is that you've forward declared class C
in global namespace instead of class scope A
. This means that there are two different class named C
one of which is declared to be in the global namespace ::C
and the second one as an inner class A::C
.
To solve this, just move the forward declaration of class C
to inside class scope A
as shown below:
header.h
class A {
public:
class C;// forward declaration moved here inside class scope A
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
};
};
Also, be careful about other logical bugs like memory leak(if any) in your program.
CodePudding user response:
class A {
public:
class C;
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};