friend classes with pointers to each other - c++

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

Multiple level friendship

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;
};

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;
};

Friends and nested classes

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_;
};

incomplete type error , when using friend functions

#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 to declare a friend that is a member function of another not yet defined class in C++?

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();
};