How can I create two classes that have member pointers to each other's class type, with full access to each other's data? In other words, I need two classes like this:
class A
{
protected:
B *p;
};
class B
{
protected:
A *p;
};
I'm having trouble with it because I'm not up to par with C++ conventions, and obviously, class A can't declare a class B because B is declared later in the code.
Thanks for the help
You should use forward class declaration.
//in A.h
class B; // forward declaration
class A
{
protected:
B *p;
friend class B; // forward declaration
};
//in B.h
class A; // forward declaration
class B
{
protected:
A *p;
friend class A; // forward declaration
};
class B;
class A {
friend class B;
protected:
B *p;
};
class B {
friend class A;
protected:
A *p;
};
Note that any member functions of A which actually use the members of B will have to be defined after the definition of B, for example:
class B;
class A {
friend class B;
protected:
B *p;
A *getBA();
};
class B {
friend class A;
protected:
A *p;
};
A *A::getBA() { return p->p; }
you must use forward declaration like:
class B;
class A{
...
friend class B;
};
class A
{
protected:
class B *p;
};
If you want to declare friendship, you need a forward declaration:
class B;
class A
{
friend class B;
protected:
B *p;
};
class B;
class A
{
protected:
B *p;
friend class B;
};
class B
{
protected:
A *p;
friend class A;
};
You could use a forward declaration by doing class B; above class A
simple use:
class B;
class A
{
protected:
B *p;
friend class B;
};
class B
{
protected:
A *p;
friend class A;
};
Using class B; means a forward declaration and this basically tells the compiler: "class B exists somewhere".
Related
In code below:
class B {
int x;
int y;
};
class A {
friend class Other;
friend class A;
int a;
B* b;
public:
A(){ b = new B();}
};
struct Other {
A a;
void foo() {
std::cout << a.b->x; // error
}
};
int main() {
Other oth;
oth.foo();
}
The indicated line fails with:
t.cpp:22:19: error: 'x' is a private member of 'B'
std::cout << a.b->x;
^
t.cpp:7:5: note: implicitly declared private here
int x;
Why friendship is not working when referring from class member to other class member?
This line:
std::cout << a.b->x;
involves accessing a private member of A (b) and a private member of B (x) within class Other. While A gave access privileges to Other, B did not, hence the error. If you want this to work, you'll need to add:
class B {
friend class Other;
};
Side-note, this declaration is meaningless:
class A {
friend class A;
};
A class already has access to its own private members. So calling it its own friend is redundant.
Although this is a weird use of friends, I assume it is for learning purposes. That said, you should fix your friends definition like this:
class B{
friend class Other; // Because you access private member x from Other::foo()
int x;
int y;
};
class A{
friend class Other; // Because you access private member b from Other::foo()
int a;
B* b;
public:
A(){ b = new B();}
};
struct Other{
A a;
void foo(){
// Access A's private member b
// Access B's private member x
std::cout << a.b->x;
}
};
Try this:
class B{
friend class Other;
int x;
int y;
};
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;
};
Ok I'm totally frazzled on this. Code is begin to swim around the screen...must sleep.
So! Ok, troubled by nested classes and friends.
here is the pseudo-code
class A{
public:
//constructor
// member functions
private:
class B{
//private
int a();
};
class C{
//private
int b();
};
};
So once an object of type A has been created, I would like it to access a() and b(). I know that I have to use a friend function for this. So where should I put friend class A. Is that the right expression?.
If you would like to access a() and b() from within class A you need to place the friend declaration inside of class B and class C. However, a() and b() are not members of class A so you cannot access them in the way you are thinking. Instead you also need to add forwarding functions to A.
class A
{
public:
//constructor
// member functions
private:
class B
{
//private
int a();
friend A; // <-- make A a friend
};
class C
{
//private
int b();
friend A; // <-- make A a friend
};
public:
// forwarding function for a
int a()
{
return bdata_.a();
}
// forwarding function for b
int b()
{
return cdata_.b();
}
private:
B bdata_;
C cdata_;
};
#include <stdio.h>
class B;
class A;
class A
{
int a;
friend int B::f();
};
class B
{
int b;
class A x;
public:
int f();
};
int B::f()
{
// ...
}
main()
{
class B b;
b.f();
}
ERRORS:
a.cpp:9: error: invalid use of incomplete type ‘struct B’
a.cpp:2: error: forward declaration of ‘struct B’
The issue cannot be solved by placing definition of B before A as
B has an object of type A.
For this example making B a friend class would do, but in
my real code I have more member functions in B (so I need alternative solution).
Finally, can somebody give me links that explain what the compiler does when it comes
across a forward declaration, declaration, definition.
You simply cannot do what you want to do as-is. To make that friend function declaration in class A the nature of class B needs to be known prior to the definition of class A. To make class B contain an instance of class A the nature of class A must be known prior to the definition of class B. Catch-22.
The former does not apply if you make class B a friend class of class A. The latter does not apply if you modify B to contain a pointer or reference to an instance of class A.
DefineB before A, and declare a pointer to A as member data of B:
class A; //forward declaration
class B
{
int b;
A *px; //one change here - make it pointer to A
public:
int f();
};
class A
{
int a;
friend int B::f();
};
Or, you could make the entire class B a friend of A, that way you don't have to make the member data pointer to A.
class B; //forward declaration
class A
{
int a;
friend class B;
};
class B
{
int b;
A x; //No change here
public:
int f();
};
Forward declare class A; define class B; define class A; define B::f.
#include <cstdio>
class A;
class B
{
int b;
public:
int f();
};
class A
{
int a;
friend int B::f();
};
int B::f()
{
}
main()
{
class B b;
b.f();
}
How I declare B's constructor to be a friend of A? I tried:
class A
{
private:
A();
public:
friend B::B();
};
class B
{
public:
B();
};
replace B:: with class;
class A
{
private:
A();
public:
friend class B;
};
class B
{
public:
B();
};