A bit of a noob question:
I need classes A and B such that A has a B* member and B has an A* member.
When compiling I get "error: ISO C++ forbids declaration of ‘B’ with no type". How can I get around this?
Forward declare B (or A )
class B; //forward declaration of B
class A
{
B *b;
};
class B
{
A *a;
};
Forward declare one of class a or b.
class b; //forward declaration
class a{
//class a stuff
b* ptrtoB;
};
class b{
//class b stuff
a* ptrtoA;
};
You can also inline forward declare one of the classes if nothing else is using it: class B* pMemberB; al la C style
Related
I have this class that compiles in VC14, but when I try to compile in gcc 4.8.5, it doesn't work, I get "error: C was not declared in this scope".
class A
{
};
class B : public A
{
friend class C;
friend class D;
private:
class BB
{
std::list<C> c;
std::list<D> d;
};
};
class C : public B::BB
{
};
class D : public B::BB
{
};
I tried to forward declare "class C" before the definition of class B, but it gives me an error because it doesn't have the same definition as "class C : public B::BB", and I can't put that definition because BB is private... I'm not sure what to do.
Thanks
Forward declarations that use friend are different from other forward declarations. Writing friend class C; within the definition of B declares that there is a class called C in the enclosing namespace (i.e., the global namespace) but does not actually introduce the name C into that scope. Therefore, you can't write something like List<C> because the name C cannot be found. You should do this:
class C;
class D;
class B : public A
{
friend class C;
friend class D;
private:
class BB
{
List<C> c;
List<D> d;
}
}
The namespace-scope declarations actually introduce the names C and D into the global scope. Then, the friend declarations make those classes friends of B.
At the time you do
List<C> c;
List<D> d;
the compiler has no idea what C and D are--you haven't declared/implemented them yet!
You don't have to completely implement them, but you'll need to at least tell the compiler they're class that'll be implemented at some point. You can do that with:
class C;
class D;
Full working example (with some minor fixes like adding semicolons to make it compile): ideone
I am writing a small c++ - program containing a similar structure to the following:
class A {
B * someObjects;
};
typedef A* APointer;
struct B{
APointer a;
int n;
}
Trying to compile this gives a "identifier is undefined" error since struct B is not known inside class A. Otherwise declaring struct B before class A should still give a similar error, since then B does not know APointer, or APointer does not know A. Is there any possibility to make class A and struct B being good friends?
Thanks in advance!
You need to forward declare B as the compiler has no idea what B is when it is used in A. B is considered an incomplete type in A and you are allowed to have a pointer or reference to B in A. You can change your code to:
struct B;
class A {
B * someObjects;
};
typedef A* APointer;
struct B{
APointer a;
int n;
};
Have you ever heard the term Forward Declaration! Your compiler don't know about B yet. So give a declaration of B first.
struct B; // forward declaration
class A {
B * someObjects;
};
//... rest of the code
I want to define two classes, A and B. A has a data member which is a Class B object and is in-class initialised. A also has a method to retrieve the value in this B type data member and this method would be declared as a friend method in B. Here is my code:
class A{
public:
int getBValue();
private:
B b=B(1);
};
class B{
public:
friend int A::getBValue();
B(int i):value(i){}
private:
int value;
};
int A::getBValue(){
return b.value;
}
And unsurprisingly the compilation had failed because of unknown type B in class A definition. I had tried to swap the definitions of A and B in the source and the result was even worse. Is there a possible way to resolve this cross reference issue between A and B?
If this is the complete code as you have it, then the problem is that the compiler doesn't know what a B is at the time it is compiling class A. One way to solve it is by creating a pointer to B instead of having a B itself:
A.h
#ifndef CLASS_A
#define CLASS_A
class B;
class A{
public:
int getBValue();
private:
B *b;
};
#endif
B.h
#ifndef CLASS_B
#define CLASS_B
#include "A.h"
class B{
public:
friend int A::getBValue();
B(int i):value(i){}
private:
int value;
};
#endif
A.cpp
#include "A.h"
#include "B.h"
int A::getBValue(){
return b->value;
}
Replacing an embedded member of type B with a pointer (or reference) to a B changes the way your class works and needs additional care when copying objects of class A.
When you reverse the definitions, you cannot make a member function of class A a friend of class B, because the type of A is incomplete at the time of the friend declaration. But you can make the entire class A a friend.
A solution with class A having an embedded member of class B could look like this:
class A;
class B{
public:
friend class A;
B(int i):value(i){}
private:
int value;
};
class A{
public:
int getBValue();
private:
B b=B(1);
};
int A::getBValue(){
return b.value;
}
Changes made:
Declared B before A. A forward declaration for A is used.
Made the class A a friend of B. This works even when A is not yet fully defined.
Compiles with g++ version 4.7.2 (-std=c++11 needed for B b=B(1);)
Anyway, having a member of class A accessing a private member of class B is something which can (and should) almost always be avoided (see Laszlo Papp's comment on your post).
So, I want something like:
class A{
B member;
};
class B{
A function();
};
No matter in which order I declare them, I get an incomplete type error (and I pretty much understand why).
How can I solve this? I don't want to use pointers or to have the function defined outside the B class. Also, declaring them before as
class A; class B;
doesn't seem to work either.
No need for class definition when declare a function.
class A;
class B{
A function();
};
class A{
B member;
};
This order will work:
class A;
class B {
A function();
};
class A {
B member;
};
class A{
public:
B b;
};
class B{
public:
A a;
};
I can't write in A class "B b" because class B defined below. Is any way to make it work?
thanks
This is not possible. You need to use a pointer or a reference in one of the classes.
class B; // forward declare class B
class A {
public:
B * b;
};
class B {
public:
A a;
};
As to why it isn't possible: A contains a B contains an A contains a B ... There's no end to the recursion.
If you're used to languages (such as e.g. java) where all object variables are pointers/references by default, note that this is not the case in c++. When you write class A { public: B b; }; a complete B is embedded into A, it is not referred to within A. In C++ you need to explicitly indicate that you want a reference (B & b;) or a pointer (B * b;)
Think about it: Inside an object of class B there's an object of class A, and inside it there's an object of class B. This is physically impossible! What will be the size of object B?
sizeof(B) > sizeof(A) > sizeof(B)
You must use pointers, like the other answer suggested.
There is no way to make it work. You should use forward declaration and a pointer to one of the class
class B;
class A{
public:
B *b;
};
class B{
public:
A a;
};
That is because when you're writing B b the compiler must know what B is. But if you make a forward declaration then compiler will know that B is some class and you will be able to create pointers and references of B.
Only if you change at least one of the two member objects to a pointer. You would be able to declare a member pointer to such an object by forward-declaring the other class, like this:
class B;
class A{
public:
B* pb;
};
class B{
public:
A a;
};
The reason for this:
The compiler needs to know how objects of each class (A and B) will be laid out in memory. This includes how much memory will be needed for each object. Since class members require an amount of memory that depends on their members, it follows that the compiler can only allow you to declare a class member if it has seen the declaration of that member's class first.
Pointers, on the other hand, always take up the same amount of memory. This is why it's enough for you to tell the compiler "B is a class; I want a pointer to B here". The "B is a class" part corresponds to the class B; line above, which is called a forward declaration.