C++ structs Interdependency - c++

Hello i have structures declared in the same Header file that need eachother.
struct A; // ignored by the compiler
struct B{
A _iNeedA; //Compiler error Here
};
struct A {
B _iNeedB;
};
this work normally
class A;
class B{
A _iNeedA;
};
class A {
B _iNeedB;
};
// everything is good
Thank you very much!

This can’t work: A contains B contains A contains B contains …. Where to stop?
All you can do to model cyclic dependencies is use pointers:
class A;
class B {
A* _iNeedA;
};
class A {
B* _iNeedB;
};
Now the classes don’t contain each other, merely references to each other.
Furthermore, you need to pay attention that you can’t use things you haven’t defined yet: in the above code, you have declared A before defining B. So it’s fine to declare pointers to A in B. But you cannot yet use A before defining it.

I answer my own question.
the fact is what im doing is not exactly what i posted but i thougt it was the same thing, actually i'm using operators that take arguments. Thoses operators body must be defined after my structs declarations (outside the struct),
because struct B don't know yet struct A members...
I said it was working with classes because with classes we usualy use CPP file for methods definition, here i am not using any cpp file for methods i use in my structs
I was about to delete this post but you guys are too fast ;),
Here an example
struct A;
struct B {
int member;
bool operator<(const A& right); //body not defined
};
struct A {
int member;
bool operator<(const B& right)
{
return this->member < B.member;
}
};
bool B::operator<(const A& right) //define the body here after struct A definition
{
return this->member < A.member;
}

Related

Alternative for forward declaration: two classes using each other

I have class A which has to implement some functions. Since implementing one of them needs it's own data structures, I assumed A contain another class B, which has all needed data structures and functions. However, B is also need to use data structures and functions of A, as well. I used two classes calling each others using forward declaration. But there is still problems. For example, I need to make all data structures in A public, in order to B can access it. I tried using friend classes, but when I declare B as an abstract classes with sub-classes which implements B's functionalities, I need to make all data structures of A, as public. Because friend class doesn't work for inherited sub-classes, all data structures of A, needs to be public. This makes my design quite messy.
class B;
class A{
protected:
int ds[100];
B * b;
public:
a_func(){
b->b_func();
}
};
class A;
class B{
A * a;
public:
b_func(){
a->a_func();
}
};
class sub_B:public B{
public:
b_func(){
a->a_func();
a->ds ...;
}
}
My question is: is there any alternative design?
I also tried making A an abstract class and class B implements a function of it, however, it doesn't conceptually makes sense to build an object of B, when I want an object of A.
You don't have to provide member function definitions inside a class definition:
class A;
class B;
class A {
// no need for public
B * b;
void a_funct(void);
};
class B {
// no need for public here, too
A * a;
void b_funct(void);
};
// the following goes in a source file,
// otherwise you should mark it as inline
void A::a_funct() {
b->b_funct();
}
void B::b_funct() {
a->a_funct();
}
Note that above code serves only as example, in its current shape it's nothing but a fancy endless (recursion) loop.

Circular dependency issues with inheritance and returning instances

I have two classes in separate headers:
struct A {
virtual B getB();
}
template<typename T>
struct Basic : public A {
}
typedef Basic<int> B;
Both headers need to include each other, which is not ideal due to circular dependency.
However, A::getB() returns an instance, so I can't forward declare to avoid the include, and Basic inherits A, so its the same deal there. Basic must inherit A, but A doesn't NEED the getB() function (although, it is highly preferable).
I must avoid the circular dependency, but am I going about this the wrong way?
Note: the A class will be inherited by a lot of other classes further down the line, hence why getB() is virtual. And Basic is a template class, so it's definition is inside it's header as well. getB() must return an instance (anything coming out of getB() is expected to be local to getB(), which is why it can't return a pointer nor a reference).
You can forward declare if you are returning by value.
So in your example, you'd have to do the following:
template <typename> struct Basic;
typedef Basic<int> B;
struct A {
virtual B getB();
};
do the following:
struct A {
virtual B* getB();
}
That is, struct A must refer to struct B only through pointers. Then you can solve the issue by forward declaring struct B before the definition of struct A.
Update After Clarification:
You can do something like the following then:
template <typename> struct Basic;
typedef Basic<int> B;
struct A {
virtual B getB();
};
template<typename T>
struct Basic : public A {
};
// definitions of member functions for struct A below here!!!
B A::getB() { B b; return b;}
int main()
{
A a;
B b;
return 0;
}
Have in mind though that definitions of member functions for struct A must be under definition of struct B.

How to omit private non-virtual methods from class definition?

Lets say I have something like the following:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
}
a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
something_complicated& A::get_complicated() { return b_->x; }
Unfortunately, in this case, a.cpp will fall to compile because "get_complicated()" is not a method of A.
So, we can try this:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
something_complicated& A::get_complicated();
}
But then a.hpp fails to compile because something_complicated isn't defined.
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out.
The only way I can think of doing this without making b_ public nor including something_complicated.hpp in a.hpp is the following:
a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
#define get_complicated ((b_->x))
Surely I don't have to define a macro to get around this issue? Any alternatives?
The easiest solution is probably to wrap a reference to the complicated type in a class, forward declare that in a.hpp, and define it in something_complicated.hpp.
a.hpp:
class B;
class complicated_ref;
class A
{
public:
complicated_ref get_complicated();
private:
std::unique_ptr<B> b_;
};
something_complicated.hpp:
// ... complicated definitions ...
typedef whatever something_complicated;
struct complicated_ref
{
complicated_ref(something_complicated & thing) : ref(thing) {}
something_complicated & ref;
};
Now a.cpp and anything that needs to use the complicated type must include it's header, but anything that just wants to use class A does not need to.
This is assuming that there's a good reason for some clients of A to access the complicated thing, but for B to be inaccessible to everyone. It would be simpler still to allow access to B when required, and get to the complicated thing through that.
I am afraid there is a misunderstand on what belong to the class, and what does not.
Not all methods that act on the internals of the class should be class methods, after all, we have friend functions already. I know that many people declare the helper methods as private functions, however doing so introduces needless dependencies (compile-time) and a visibility issue with friends.
When dealing with PIMPL, I tend not to use private functions. Instead, the choice is:
Making Impl (B in your case) a true class, with its own validation logic and true API
Using static free functions (or functions declared in an anonymous namespace)
Both are good, and use whichever seems most appropriate. Namely:
methods: when dealing with validation issues
free functions: for computing that can be expressed in terms of the aforementionned methods
It is deliberate on my part to search to have as few methods as possible, because those are the only ones that can screw up my class invariants, and the less they are the more confident I can be that the invariants will be maintained.
In your case, it's up to you to decide which approach suits you best.
In Action:
a.cpp
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
static something_complicated& get_complicated(B& b) { return b_.x; }
// or anonymous namespace instead
namespace {
something_complicated& get_complicated(B& b) { return b_.x; }
}
Not so different from what you had, eh ?
Note: I prefer static functions to anonymous namespaces because it's more obvious when reading. Namespaces introduce scopes, and scope are not glanced easily when sifting through a file. Your mileage may vary, both offer identical functionality (for functions).
Just avoid referring to something_complicated in a.hpp.
One solution is to replace the member function get_complicated with a free function, or a static method of another class.
.h:
class A_impl_base {
A_impl_base() {}
friend class A_impl; // all instances of A_impl_base are A_impl
}; // this stub class is the only wart the user sees
class A
{
private:
std::unique_ptr< A_impl_base > b_; // this is not a wart, it's a pimpl
friend class A_impl;
}
.cpp:
class A_impl : A_impl_base {
static A_impl &get( A &obj ) { return * obj.b_; }
static A_impl const &get( A const &obj ) { return * obj.b_; }
};
What's wrong with:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
public:
B& get_B();
}
If your clients want to get something complicated out of B, then let them #include <something_complicated.hpp>.
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out.
This is exactly what you have to do. And I don't see how being a typedef rules out a forward declaration.
If you control something_complicated.hpp you could do what the standard library does: Create a something_complicated_fwd.hpp that has appropriate forward declarations, including the types that may or may not be typedefs.

C++ circular dependency - namespace vs struct

Please educate me. Why does this compile:
struct compiles
{
struct A;
struct B
{
B(const A &a) : member(a.member) { }
int member;
};
struct A
{
A(const B &b) : member(b.member) { }
int member;
};
};
while this does not:
namespace doesnt
{
struct A;
struct B
{
B(const A &a) : member(a.member) { }
int member;
};
struct A
{
A(const B &b) : member(b.member) { }
int member;
};
}
(in MSVC 9.0)
The body of a class/struct/union definition is processed all at once, allowing references to members of classes defined later. A namespace is processed from top to bottom, and a forward declaration of struct A does not allow you to use its members without a definition. Try moving the definition of B's constructor out-of-class so you can put it after the definition of A.
In C++, class scope is special. Any declaration that extends to or past then end of the class definition is automatically extended to the regions defined by its member definitions (3.3.6 [basic.scope.class]).
This means that in the first case both the first declaration of struct A and the full definition of struct A are visible in the body of B and its constructor.
This doesn't apply to namespace scope so in the second case a.member in the constructor of B is an error because a definition of struct A isn't yet visible.
[Also tested with g++ 4.2] The first one compiles because the compiler fully picks up all the types defined within the struct before actually compiling the nested structures (think about public inline methods using private attributes that appear later within the class). Within the namespace the compiler simply works top-to-bottom and doesn't have special rules.
both will compile if you move the implementations of the constructors to the .cpp file where they should be anyway.

Class reference to parent

i'm pretty new at using C++ and I'm actually stopped at a problem.
I have some class A,B,C defined as follow (PSEUDOCODE)
class A
{
...
DoSomething(B par1);
DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
The problem is :
How to make this? If I simply do it (as I've always done in c#) it gives errors. I pretty much understand the reason of this. (A isn't already declared if I add the reference (include) of B and C into its own header)
Any way to go around this problem? (Using void* pointer is not the way to go imho)
Forward-declare B and C. This way compiler will know they exist before you reach the definition of class A.
class B;
class C;
// At this point, B and C are incomplete types:
// they exist, but their layout is not known.
// You can declare them as function parameters, return type
// and declare them as pointer and reference variables, but not normal variables.
class A
{
....
}
// Followed by the *definition* of B and C.
P. S.
Plus, one more tip unrelated to the question (seeing how you come from a C# background): it's better to pass by const reference than by value:
class A
{
...
void DoSomething(const B& par1);
void DoSomething(const C& par1);
...
}
For function declarations, parameter types are allowed to be incomplete if the function is not defined there:
class B;
class C;
class A
{
...
R DoSomething(B par1);
R DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
inline R A::DoSomething(B par1) { ... }
inline R A::DoSomething(C par1) { ... }
So you just define them after B and C become complete. But since they are defined outside the class, make them inline so multiple definitions in different translation units won't cause linker errors.
You should forward declare classes B and C before A:
class B;
class C;
class A {
...
};
At the point where B and C are referenced within A, the compiler only needs to know what kind of animals these are. With the forward declaration you satisfy the compiler. Then later you can define them properly.
use forward declaration
You can define class A; without it's implementation, before B and C, and then define it later