Multiple level friendship - c++

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

Related

Why Friend Function cannot access private members of a class

class A{
public:
void printer(){
B obj;
obj.private_data = 10; // <- fails, says member inaccessible
}
}
class B{
friend void A::printer();
private:
int private_data;
}
is it possible for printer function to access private members of class B? i tried to pass an obj of B as arg to printer but it still failed
Class A doesn't know about B to use it. Hence, postpone the definition of the function printer() until you define B, and if you need an instance of B to be a member var in A then make a forward declaration for B to declare a B* in A.
Hence, use something like what follows:
class A {
public:
void printer();
};
class B {
friend void A::printer();
private:
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10; // <- No longer fails
std::cout << obj.private_data;
}
int main() {
A a;
a.printer();
}
Demo
Why Friend Function cannot access private members of a class?
They can, but you may need to split the definition of the class up a bit.
Imaginary files added:
Define A (file a.hpp):
class A {
public:
void printer();
};
Define B (file b.hpp):
#include "a.hpp" // B must see the definition of A to befriend a member function
class B {
friend void A::printer();
private:
int private_data;
};
Define A's member function (file a.cpp):
void A::printer() {
B obj;
obj.private_data = 10;
}
To access B, you first need to define it. Thus, you can just declare the method printer and define it after you have defined the class B.
class A {
public:
void printer();
};
class B {
private:
friend class A;
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10;
}
Note, you probably want to move your methods out of your class definition anyways and into a separate .cpp file. Methods defined inside the class are implicitly marked as inline which might not be what you expect.

How can I friend a derived class function in the base class?

I have the following code:
#include <iostream>
class A {
private:
int a;
public:
void setA(int a_);
friend int B::getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int B::getA() {
return a;
}
int main() {
B myB;
myB.setA(9);
std::cout << myB.getA()<< std::endl;
return 0;
}
Compiling with g++ yields:
friend.cpp:10:16: error: use of undeclared identifier 'B'
friend int B::getA();
My thinking is that when the compiler is going through the class A definition, it does not yet know about class B. Therefore, I can forward declare B to take care of this problem:
#include <iostream>
class B;
class A {
...
That doesn't quite work:
friend.cpp:10:16: error: incomplete type 'B' named in nested name specifier
friend int B::getA();
It looks like the compiler isn't able to resolve the function as it is given.
How can I make a derived class function a friend in the base class?
Your code seems to violate the basic concept of data encapsulation. To resolve it, either make A::a protected, as #rici suggested, or define a getter in class A.
class A {
private:
int a;
public:
void setA(int a_);
virtual int getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int A::getA() {
return a;
}
int B::getA() {
return A::getA();
}

How to access private members of an abstract class from its friend class?

class A
{
private:
int a,b,c;
public:
virtual int get()=0;
friend class B;
};
class B{
//here I want to access private variables of class A that is a, b and c
};
class C:public class A
{
int get(){
//some code
}
};
How to access private members of class A in class B. I cannot create an object of class A since it is abstract. I somehow have to use an object of class C to do that but how?
class A {
friend class B;
private:
int x;
public:
A() : x(42) {}
};
class C : public A {
};
class B {
public:
int reveal_secrets(C &instance){
// access private member
return instance.x;
}
int reveal_secrets(){
// access private member of instance created inside B
C instance;
return instance.x;
}
};
void print_secrets(){
C instance;
B accessor;
std::cout << accessor.reveal_secrets(instance) << ", " << accessor.reveal_secrets() << std::endl;
}
class B will have to have an instance object to work with in the first place. That instance object is what B will look at in order to access a, b, etc .

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

friend classes with pointers to each other

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".