Complex Circular Dependency among classes - c++

I have 5 classes (A,B,C,D,E), each of which will have their own class and header files.
class A{};
class B
{
B(A&a);
};
class C
{
C(B&b);
};
class D:public A
{};
class E:public D
{
vector<C*> vc;
};
Forward declaration will not work because I also have a lot of sharepointers being used in each of those classes.

You can use forward declarations for shared pointers as well, you just need to forward declare a destructor function object as well.
Header:
struct A;
shared_ptr<A> create_A();
Impl:
struct A { ... };
struct A_destroyer { void operator()(A *p) { delete p; } };
shared_ptr<A> create_A() { return shared_ptr<A>(new A(), A_destroyer()); }

Each class can declare a destructor and define that destructor in a source including the header for the appropriate type destructed by unique/shared pointer. Than a simple forward of that type in the header will do it.
#include <memory>
// header B
struct A;
struct B {
~B();
std::shared_ptr<A> a;
};
// header A
struct A {};
// source B
#include "a"
#include "b"
B::~B() {}

Related

What is the correct way for me to access a public member of class A in class B when class B is a member of class A in C++?

In the below example I want to be able to access vector cList in class B in the function ShareData. How do I do that?
I have written a sample code. It fails to compile (Error message: B has no constructors). Even if it did, does the line cObj = new B(*this); introduce any circular dependency?
#include "stdafx.h"
#include <vector>
class B;
class A
{
public:
B* cObj;
std::vector<B*> cList;
A()
{
cObj = new B(*this);
}
};
class B
{
public:
B(A& aObj) : aObjLocal(aObj) {};
void ShareData(int result)
{
for (auto& iterator : aObjLocal.cList)
{
(*iterator).ShareData(result);
}
}
private:
A& aObjLocal;
};
void main()
{
A aMain;
B bMain(aMain);
bMain.ShareData(10);
}
Thanks in advance for sharing the knowledge.
When you are using forward declarations, you need to make sure that any usage of the forward-declared type which needs full type happens after the type becomes fully defined.
In your case, it means that your code should like following:
class B;
class A
{
public:
B* cObj;
std::vector<B*> cList;
A();
};
class B {
...
};
inline A::A()
{
cObj = new B(*this);
}
Also, while doing so, you certainly would want to get rid of owning B*, and instead use std::unique_ptr there.
The line
cObj = new B(*this);
does not work in A's constructor since the definition of B is not visible at that line. Move the implementation of A's constructor after B has been defined.
class A { ... };
class B { ... };
inline A::A()
{
cObj = new B(*this);
}
cObj = new B(*this);
You cann use B here since it's not yet defined.
Put this under the definition of B:
A::A()
{
cObj = new B(*this);
}
and remove the inline definition.

C++ classes with members referencing each other and being used

I have 2 c++ classes with members referencing each other. I am calling members of the referenced classes, so I can't use forward declarations, because I get the error "pointer to incomplete class type is not allowed"
class A {
B* b;
void foo() {
b->do_something();
}
};
class B {
A* a;
void bar() {
a->do_something_else();
}
};
Is there any way to get the includes to work here?
There is already a ticket open by a similar name but I can't use the solution there.
Just separate the definitions from the declarations:
class B;
class A {
public:
void foo();
void do_something_else(){}
private:
B* b;
};
class B {
public:
void bar();
void do_something(){}
private:
A* a;
};
//now B has a complete type, so this is fine
void A::foo() {
b->do_something();
}
//ditto
void B::bar() {
a->do_something_else();
}
You can use the prototype definitions in a header file. And the logical body in a cpp file.
After doing this you can use the forward declaration in the header( class B, class A)
Example: #TartanLlama

Declaring an object with a type which is not declared yet

Sorry I could not find a better title :) There are two structs in a header file. These structs have members of type another struct. Compiler complains that B is not declared when I declare B obj. So what should I do?
structures.h
struct A
{
B obj; // B is not declared yet
};
struct B
{
A obj;
};
Creating an object of type not declared will not be possible. Best you can have is pointer to that type.
An example of use would be like:
#include <iostream>
using namespace std;
struct A;
struct B{
A* obj;
B(){cout<<"B ctr"<<endl;}
};
struct A{
B* obj;
A(){cout<<"A ctr"<<endl;}
};
int main()
{
B obj1;
obj1.obj = new A();
A obj2;
obj2.obj = new B();
return 0;
}

How do I access a private constructor in a separate class?

I'm writing a library in C++. I have two classes in my library, A and B. I want to hide the A() constructor from any code that references my library. I also want class B to be able to call the A() constructor.
I come from a C# background and remember little of my C++. In C#, I would simply declare the A() constructor as internal. I've read that the closest way to do this in C++ is a combination of friend declarations and forward-declarations. How do I do this? Here are my three files below:
A.h:
#pragma once
class A
{
private:
A();
};
B.h
#pragma once
class A;
class B
{
public:
A createA();
};
B.cpp:
#include "A.h"
#include "B.h"
A B::createA()
{
A result; //cannot access private member declare in class 'A'
return result;
}
I've tried adding this to A.h:
public: friend A createA();
I've instead tried adding this to A.h with a corresponding forward declaration:
public: friend A B::createA();
I've instead tried adding and extern class B; to A.h and making B a class like this:
public: friend class B;
I'm at a loss.
I think this might be easier if I have the B::createA() function return a pointer to an A object rather than an A object directly, but that won't do in my case. I am emulating a closed API and the API call returns an A object rather than a pointer.
You probably just need to drop the "extern" from your third attempt to turn it into a proper forward-declaration. Try:
A.h:
#pragma once
class B;
class A
{
friend class B;
private:
A();
};
You don't need the external keyword. Make it simple:
// In A.h
class B; // Forward declaration
class A
{
friend class B; // Make all the class B friend
A();
};
// In B.h
class B
{
public:
A createA() {}
};
Live Example.
Unless absolutely necessary, you should have A construct itself (or have a factory that creates A). If you really want B to do it:
class B; // foward declared
class A
{
private:
A() {}
friend class B;
};
class B
{
public:
A CreateA()
{
A a;
return a;
}
};
int main()
{
B b;
A a = b.CreateA();
return 0;
}
Note: You must forward declare B before declaring it a friend in A.
If you want just the function as a friend:
class A;
class B
{
public:
A CreateA();
};
class A
{
private:
A() {}
friend class A B::CreateA();
};
A B::CreateA()
{
A a;
return a;
}
int main()
{
B b;
A a = b.CreateA();
return 0;
}
You can make B a friend of A:
class A
{
private:
A();
friend class B;
};

How to access parent methods from embedded class in PIMPL pattern

I have found a similar question here, but my intent is little different.
class B is the embedding class while class A is the embedded class. I want to let B::A have access to member functions of class B. I have seen compilation errors through g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2. The detailed errors are as follows:
~/Documents/C++ $ g++ embed.cpp
embed.cpp:5:7: error: ‘B’ has not been declared
embed.cpp: In constructor ‘B::B()’:
embed.cpp:10:27: error: invalid use of incomplete type ‘struct B::A’
embed.cpp:14:9: error: forward declaration of ‘struct B::A’
Is there a way that I can make it work?
Thank you
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(new B::A(this)) {}
~B(){}
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent) : parent(_parent) {} // let embedded class A has access to this parent class
~A() { parent = NULL; }
B* parent;
};
int main(void)
{
return 0;
}
This problem is solved easily if you follow the convention of having the header in one file and the implementation in another.
In file b.h:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent);
~A();
B* parent;
};
In file b.cpp:
B::B(void)
:impl(new A(this))
{
}
//other methods and such
My compiler was giving me a different error: in the constructor for B, you were default-constructing an object that had no default constructor (because it's an incomplete class). The solution is to implement the B constructor after class A has been fully defined, and the header/implementation separation is a natural way to achieve that.
Just separate the definition from the declaration:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
// define class B::A
B::B() : impl(new B::A(this)) { }
B::~B() { }
By the time you need to call B::A::A(), it'll already be defined.
You could separate this into three files, B.hpp, BA.hpp and B.cpp, and you would only need to ship B.hpp to the client.
You just can't. If you want to use A, then you have to know all about A. But there maybe another approach:
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(newA()) {}
~B(){}
private:
static Abase *newA();
class Abase{}; // want to hide the implementation of A
Abase* impl;
friend class A;
};
And you define you class A : B::Abase in another file, and implement B::newA() to return a pointer to A.
Code not tested.