I have two classes like this:
#include <iostream>
class A {
public:
class B {
public:
void printX(void) const { std::cout << A::x << std::endl; }
};
private:
int x;
};
Obviously this piece of code doesn't work because B
can't access x
, but is there a way to make it work?
I've tried using friend class
keyword in both classes like this:
class A {
public:
class B {
public:
friend class A;
void printX(void) const { std::cout << A::x << std::endl; }
};
friend class B;
private:
int x;
};
But it didn't work either, and I can't figure out if it's even possible.
CodePudding user response:
As the error message should tell you, A::x
isn’t a static member so you need an object instance to access it. If you add a reference to instance of A
to B::A
, you can use that to access A::x
.
For example, the following works:
class A {
public:
class B {
public:
B(A const& a) : a(a) {}
void printX(void) const { std::cout << a.x << std::endl; }
private:
A const& a;
};
private:
int x;
};
Note that using a reference member has several implications. Notably, you can now no longer reassign instances of type A::B
, nor are its instances movable. As a consequence, it’s often convenient to hold a pointer rather than a reference to A
inside A::B
. Either way, you’ll need to ensure that instances of A::B
do not outlive the A
instance they refer to, otherwise you end up with a dangling reference.
CodePudding user response:
According to the C 17 Standard (14.7 Nested classes)
1 A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules (Clause 14) shall be obeyed.
The problem with the provided code is that x
is not a static data member of the class A
. You need to provide an object of the class A
the data member x
of which will be accessed within an object of the nested class.
For example
class A {
public:
class B {
public:
void printX( const A &a ) const { std::cout << a.x << std::endl; }
};
private:
int x;
};
A::B().printX( A() );