So I am creating a project that involves having vectors nested inside one another, but the structure won't compile. I think this is a case of circular dependency, but all of the fixes I've seen seem to only apply to code involving header files and separate translation units.
#include <iostream>
#include <vector>
class A {
public:
virtual ~A();
};
// The following forward declaration statements didn't solve the
// compiler error:
// class C;
// class C : public A;
class B : public A {
std::vector<A*> Avector;
public:
void addC(C* Cin){Avector.push_back(Cin);}
~B();
};
class C : public A {
std::vector<A*> Avector;
public:
void addB(B* Bin){Avector.push_back(Bin);}
~C();
};
int main() {
B b;
C c;
b.addC(&c);
c.addB(&b);
}
I've tried forward declaring with
class C;
Class C : public A;
But none of it seems to work.
The error I get is:
\test\test\source.cpp(15): error C2061: syntax error : identifier 'C'
\test\test\source.cpp(15): error C2065: 'Cin' : undeclared identifier
Is this sort of code implementable?
"... but all of the fixes I've seen seem to only apply to code involving header files and separate translation units."
I well agree that a popular Q&A like Resolve circular dependencies in c++ doesn't really answer your question how to handle this within a single implementation file (header or not).
However IMHO it's considered the better practice (and as you could pick up by these pointers), to separate out class declarations in headers and implementation/definition into their own translation units.
Even with header only (e.g. template class) libraries, you should consider to provide a separate class declaration (without inlined code), and provide the implementation in a separate source file, that's included there.
Your problem is actually here:
class B : public A {
// ...
void addC(C* Cin) { Avector.push_back(Cin); }
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// ...
};
At this point (even with a forward declaration of class C;
) the compiler doesn't know how to convert C*
to A*
, because the information about the inheritance relationship is missing (and no, you can't make forward declarations like class C : public A;
).
"Is this sort of code implementable?"
You can do all that in a single translation unit/header file:
Instead of inlining the function definition with B
's class declaration, you should separate it out to be seen after the full declaration of class C
:
class C;
class B : public A {
// ...
void addC(C* Cin);
};
class C : public A {
// ...
};
inline void B::addC(C* Cin) { Avector.push_back(Cin); }
class C
will see the full declaration of class B
anyway (because of declaration order). Thus it's OK to use the implementation
void addB(B* Bin) { Avector.push_back(Bin); }
from within the class C
declaration.
I'd tried forward declaring, and I'd tried putting the function implementation after the second part, but I hadn't tried both at once. The fixed code for anyone googling this 10 years later:
#include<iostream>
#include<vector>
using namespace std;
class C;
class A
{
public:
virtual ~A();
};
class B : public A
{
public:
vector<A*> Avector;
void addC(C* Cin);
~B();
};
class C : public A
{
public:
vector<A*> Avector;
void addB(B* Bin)
{
Avector.push_back(Bin);
};
~C();
};
void B::addC(C* Cin)
{
Avector.push_back(Cin);
}
int main()
{
}
My thanks to πάντα ῥεῖ , and a shout out to Jarod42.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With