Basically I have 2 classes under a namspace, and I want to give one of the methods of one class (call it B::fun) access to the private member of the other class (call it class A). However, I can't seem to get it to work. Here is a simple example that illustrates the problem:
namespace ABC // this could be global too
{
class A;
class B
{
public:
int fun(A member);
};
class A
{
public:
friend int B::fun(A member);
private:
int aint;
};
int B::fun(A member)
{
return member.aint; // error: member ABC::A::aint is inaccessible
}
}
Why do I get this error?
NOTE: Seems to be a compiler issue (using VC++ 11).
Actually, with both G++ 4.8.1 and CLang++ 3.3 I'm getting an error in the friend line:
g++: error: 'int ABC::B::fun(ABC::A)' is private
clang++: error: friend function 'fun' is a private member of 'ABC::B'
That is, the error is that ABC::B::fun() is private, so the friend declaration fails, and then the line you signaled fails as a consequence.
This happens because simply you cannot make a friend that you cannot access.
The solution is to make ABC::B::fun() public, or make friend the whole B, or something similar.
By the way, the namespace has nothing to do with your error, but IMO it would be clearer if your friend declaration were simply:
friend int B::fun(A member);
as you are already inside namespace ABC.
Change your friend declaration inside A
class A {
friend class B;
int aint;
};
Alternatively, to only friend the single method, you need to make A a friend of B since the method you're friending is private. Or you could make fun(A) public.
namespace ABC
{
class A;
class B
{
friend class A;
int fun(A member);
};
class A
{
friend int B::fun(A);
int aint;
};
int B::fun(A member)
{
return member.aint;
}
}
Related
I have a problem. In the following example, there is a static private member variable called private_b of class A inside namespace a. And then I'm trying to access that variable from class B, which I have declared to be a friend of class A, but it doesn't work, with a compile error from GCC:
error: ‘B* a::A::private_b’ is private within this context
class B;
namespace a {
class A {
private:
static B* private_b;
friend class B;
};
B* A::private_b = nullptr;
}
class B {
public:
void foo() {
B* foo = a::A::private_b; // Error here
}
};
I don't understand why I can't access it, and how to get around this problem. I really want class A to be inside that namespace, and class B doesn't make sense to be inside that namespace. I searched for this on the internet, but couldn't find this exact case, or couldn't find a solution for this case.
friend class B; declared friendship with B in the same namespace a. You may want friend class ::B;.
Note, friend class B; does not refer to the global forward declaration class B, it has own forward declaration class B after the keyword friend.
Is it possible to create a class that has a friend function of a forward declared class? If I wanted to create two classes that have friend functions of each other, how would I do that? This attempt fails with the message invalid use of incomplete type 'class Y':
class Y;
class X
{
public:
void a();
friend void Y::b();
};
class Y
{
public:
void b();
friend void X::a();
};
I also tried forward declaring void Y::b(); right after class Y; which similarly did not work. Would this example be an indicator of bad design on my part or just a limitation of C++?
consider the following example.
class A
{
int member;
};
class B
{
A& a_ref;
void manipulate()
{
a_ref.member++;
}
};
Now, obviously, B::manipulate can not access a_ref. I would like to allow (only) class B to get (reference) to A::member. I know that there exists friend keyword, but I do not know how to use it properly. My intention is, that I could change B::manipulate implementation to become this
int& A::only_B_can_call_this() // become friend of B somehow
{
return member;
}
void B::manipulate()
{
a_ref.only_B_can_call_this()++;
}
To make B a friend:
class A
{
int member;
friend /*class*/ B; // class is optional, required if B isn't declared yet
};
Note that friends are anti-patterns - if something is private, it probably shouldn't be accessed. What are you trying to accomplish? Why isn't A self-contained? Why does another class need to access its internal data?
Use friend if you have valid answers/reasons for these questions.
You simply add friend class <class_name>; to the class that wants to make its members accessible, where <class_name> is the name of the class that you want to provide access for.
class A
{
friend class B; // allow class B to access private members of A
int member;
};
class B
{
A& a_ref;
void manipulate()
{
a_ref.member++;
}
};
Can i put definition of friend function / class inside another class? I mean something like this:
class Foo
{
friend void foo() {} // 1
friend class Bar {}; // 2
};
gcc compiles friend function, but can't compile friend class.
You can define a friend function in the friend declaration, and it has interesting behavior that cannot be obtained any other way (in the case of the enclosing type being a template).
You cannot define a friend class in the friend declaration, and there is no need for that. If you want to create a new type inline with full access, you can just create a nested type. Being a member it will have full access to the enclosing type. The only difference is that the type will not be found at namespace level, but you can add a typedef if needed (or alternatively, define the class at namespace level and just declare the friendship inside the class).
class Outer {
int x;
class Inner {
static void f( Outer& o ) { o.x = 5; } // fine
};
};
n3337 11.3/2
A class shall not be defined in a friend declaration. [ Example:
class A {
friend class B { }; // error: cannot define class in friend declaration
};
—end example ]
But you can use something like
class Foo
{
friend void foo() {} // 1
class Bar { };
friend class Bar; // 2
};
You can make a nested class which, according to defect report 45, has access to the private members of the class. Is this what you meant?
"A nested class is a member and as such has the same access rights as any other member."
This may not work in all compilers because prior to this C++ standards defect report, nested classes were given no special access.
Change the code to:-
class Foo
{
friend void foo() {} // 1
friend class Bar ; // 2
};
i.e. if I define operators == and + in my class in a private section, can they be accessible from main?
It works in MSVS 2008 and 2010 but for me it seems to be a bug in a compiler. Is it so?
Functions or members declared under private access specifier will not be accessible outside the class member functions.
There are 3 access specifiers for a class/struct/Union in C++. These access specifiers define how the members of the class can be accessed. Of course, any member of a class is accessible within that class(Inside any member function of that same class). Moving ahead to type of access specifiers, they are:
Public - The members declared as Public are accessible from outside the Class through an object of the class.
Protected - The members declared as Protected are accessible from outside the class BUT only in a class derived from it.
Private - These members are only accessible from within the class. No outside Access is allowed.
Friends to the rescue!
Declaring a function as friend inside another class allows that function to access all the member functions inside the class irrespective of the access specifier rules. friend It is a way to bypass the access specifier rules laid out in C++. Similary, a class declared as friend inside another class will allow the class being declared as friend to have access to all the members of the class. Note that the friend declaration can be given under any access specifer and it will have the same effect.
An source code example:
class MyClass
{
public:
int a;
protected:
int b;
private:
int c;
friend void doSomething(MyClass obj);
};
void doSomething(MyClass obj)
{
obj.a = 10; //Allowed
obj.b = 20; //Allowed,
obj.c = 30; //Allowed,
}
int main()
{
MyClass obj;
obj.a = 10; //Allowed
obj.b = 20; //Not Allowed, gives compiler error
obj.c = 30; //Not Allowed, gives compiler error
}
So in your usage if you are using friend then you can have access to the private members of the class or else your compiler is buggy you should consider changing it!
You will have to show the code to get a sensible explanation of why the compiler is accepting it. My guess is that you are implementing them as friend free functions. At any rate, for the sake of argument, assume you have:
class bar {
friend bool operator==( bar const &, bar const & ) {
return true;
}
bar operator+( bar const & ) {
return *this;
}
};
int main() {
bar a, b;
a == b; // ok
//a + b; // nok: operator+ is private from this context
}
And now the explanation. In the example, operator+ is declared as a member function inside a private section, as such, access specifiers apply and unless main is a friend of the class it will not have access to it. On the other hand operator== is implemented as a free function (even if the definition is provided inside the class braces) and access specifiers do not apply there.
The code is almost equivalent (there is a small difference when it comes to lookup) to:
class bar {
friend bool operator==( bar const &, bar const & ); // just declare as friend
//...
};
bool operator==( bar const &, bar const & ) {
return true;
}
Where it is much simpler to reason about accessibility of operator== from the main function.
Yes, it is a bug. They are accessible only by friend functions and friend classes. All other shouldn't have access to private section.
The first answer is : No. If its accessible from outside then what is the point of being it private?
However, there is a twist.
If you make main() friend of the class, then its accessible only from main(). So the second answer is : it actually depends: Only member functions and friends can access the private member of a class.
class A
{
int data; //private
friend int main(); //make main() friend of A
};
int main()
{
A a;
a.data = 100; //okay - main() is a friend of class A
}
void f()
{
A a;
a.data = 100; //error - f() is not a friend of class A
}
That means, I infer that operator== and operator+ must be friends of the class in your code.
If you haven't added a friend declaration for main (don't know if that is even possible), the answer is no, so you apparently have found a compiler bug.