Friend function cannot access private member variable - c++

I'm having two classes, PlayerCharacter and Ability. The Ability class has an pure virtual function which I declare as a friend to PlayerCharacter. However, I seem to be unable to access the private members within the friend declared function. Is it something I overlook?
I have attemped to declare the child function rather than the virtual one as the friend function, but to no effect.
player_chracter.h :
#include "ability.h"
class PlayerCharacter : public Character {
private:
// Friend function
friend bool Ability::ExecuteAbility(PlayerCharacter& in_player);
// This doesn't work either
//friend bool Dash::ExecuteAbility(PlayerCharacter& in_player);
// Private variable
float top_speed_;
}
ability.h :
//Forward declaration
class PlayerCharacter;
class Ability {
public:
Ability();
~Ability();
virtual bool ExecuteAbility(PlayerCharacter& in_player) = 0;
};
//---------------------------------------------------------
class Dash : public Ability {
public:
Dash();
~Dash();
bool ExecuteAbility(PlayerCharacter& in_player);
};
ability.cpp :
#include "ability.h"
#include "player_character.h" //Follow through on forward declaraction
bool Dash::ExecuteAbility(PlayerCharacter& in_player) {
float example = in_player.top_speed_;
}
In the code above, why cannot I access top_speed_ and put it in the float example variable?

As per [class.friend]/10, friendship is not inherited.
A derived class does not automatically become a friend of a class just because its parent class is a friend of that class.
The reason why the below also does not work either is probably because Dash is not defined before the function ExecuteAbility is defined.
friend bool Dash::ExecuteAbility(PlayerCharacter& in_player);
However, with the proper order of definitions it will work. See DEMO.

From cppreference:
Friendship is not transitive (a friend of your friend is not your friend)
Friendship is not inherited (your friend's children are not your friends)
Even if Dash::ExecuteAbility overrides a friend function from its base class, it does not benefit from it. You'll have to rethink your design.

Related

Friend function and implementation

I came across the following code
class ExDer1 : public ExBase
{
public:
friend int Der1Fn()
{
....
}
};
I am a little confused here with
friend int Der1Fn()
{
//This has an implementation .Why is it a friend then ? since it can access the private/protected variables of the ExDer1 class ?
}
Normally I would expect to see something like the following
friend int Der1Fn(); //No implementation. Indicating that the Der1Fn is a method outside this class
which basically would mean that a function int Der1Fn() would access the private variables of the class ExDer1. However this has an implementation. Could any one please explain what this means ?
Update:
So if I have the following code
class ExDer1 : public ExBase
{
public:
friend int Der1Fn()
{
std::cout << "Hello World";
}
};
int main()
{
Der1Fn(); // error C3767: 'Der1Fn': candidate function(s) not accessible
//.....
}
How do I call Der1Fn ?
Friend function ( or class) can be defined outside or inside class as well. If you define it inside you should provide matching declaration in correct scope, or argument dependent lookup will take place.
Following examples are logically same:
Example 1:
int Der1Fn();
class ExDer1 : public ExBase
{
public:
friend int Der1Fn()
{
....
}
};
Example 2 (recommended):
int Der1Fn()
{
....
}
class ExDer1 : public ExBase
{
public:
friend int Der1Fn();
};
How do I call Der1Fn ?
As simle as this.
You can declare the body of the friend function inside the the class definition (like for any type of function).
However the friend function follows the same basic rules of every function ever implemented : it's a bad practice to declare it in the class definition (inlining , recompilations of all dependent objects on change etc) .
You referenced a MSDN example. They just made the example like to show how scoping is done. The function Der1Fn() is in the global namespace, not in the ExDer1::Der1Fn() .
For your updated post :
The class Der1Fn() doesn't have access to the ExDer1's this (it's not a part of the class, it's an external function, think of it as being static).
However, inside the Der1Fn()'s body you can access private member variables of ExDer1 type of objects.
You'd make a function a friend if it needs to access private members of the class, but shouldn't be a member. The friend function can be implemented either inside or outside the class.
If a friend function is declared (and defined) only within the class, then it's scoped within the surrounding namespace, as if you'd defined it there; but it can only be found by argument-dependent lookup (ADL) - that is, it can only be found if called with a type from the same namespace as one of its arguments.
In this case, the function has no arguments, so can't be found at all - which is why you can't call it from main, or indeed from anywhere else. You'll need to declare the function outside the class, as well as in the friend declaration inside the class.
It would be more useful if it had an argument of the class type (or another type scoped in the same namespace); then it would be found when called with that argument type:
class ExDer1 : public ExBase
{
public:
friend int Der1Fn(ExDer1 const &)
{
....
}
};
int main()
{
ExDer1 obj;
Der1Fn(obj); // Found by ADL
}
Defining a friend inside a class is particularly useful for operator overloads which are (usually) only accessed by ADL anyway.

How to provide protection to friend function in C++

I have just started learning friend functions in C++.This is the program which I am using for the concept exploration.
#include<iostream>
using namespace std;
class one
{
private:
int age;
public:
one()
{
age=1;
}
void setData(int num)
{
age=num;
}
friend int returnOne(one a);
};
int returnOne(one a)
{
return a.age;
}
class two
{
private:
int roll;
public:
two()
{
roll=0;
}
void setData(int num)
{
roll=num;
}
friend int returnTwo(two b);
};
int returnTwo(two b)
{
return b.roll;
}
int main()
{
one a;
two b;
a.setData(10);
b.setData(12);
cout<<returnOne(a)<<endl<<returnTwo(b)<<endl;
}
Now I am worried that the security of class one and two has been compromised as now anyone can use those globally defined friend functions to access class one's and class two's private members.
How can I provide protection to these friend functions or restrict their usage?
friend ship is mutual. Unless one declares the function as friend in the class definition a function cannot be friended, so it's a choice. If you make it you have to live with it. It makes no sense to make a function friend and then try to prevent it from accessing the class internals because that is exactly the purpose of keyword friend.
Do not misuse or misinterpret friendship.
friendship is used to indicate a intentional strong coupling between two entities. If there exists a special relationship between two entities such that one needs access to others private or protected members but You do not want everyone to have access by using the public access specifier then you should use friendship.
Declaring a friend function in a class extends the classes public interface. You are basically extending the class with more functions (at the cost of tightly coupling those functions).
So you can not stop people using those functions just like you can not stop people using public member methods on your class (they are all part of the public interface).
But you could re-design your friend functions so they do not expose implementation details.
Why not define operator<< for your class instead of a functions that access particular members (this is assuming you are providing these functions simply for streaming (if not then the point is mute)).
std::ostream& operator<<(std::ostream& s,two const& b)
{
return s << b.roll;
}

friend declaration in protected section

Is there a meaning to declare friendship in the protected section, rather than in public?
For example in this code:
class Shape {
//...
protected:
friend ostream& operator<<(ostream& os, const Shape& s);
virtual void print(ostream& os) const = 0;
};
[Note that Shape is abstract]
Could I have just put the friend and the function declaration in public?
Thanks!
Is there a meaning to declare friendship in the protected section,
rather than in public?
No. The friend class has the same level of access irrespective of whether the friend declaration appears in either the public, protected or private sections of the class definition.
link
Could I have just put the friend and the function declaration in
public?
thus yes, it doesn't matter whether declaration has been found in private, public or protected part of your class.

Call private member within the method belonging to the class itself

I encountered this problem when implementing a class:
class Cell {
bool isAlive;
int numNeighbours;
//...omit irrelavent private members
public:
Cell(); // Default constructor
~Cell(); // Destructor
void setLiving();
....
};
void Cell::setLiving(){
isAlive=true;
}
class Grid{...
friend std::ostream& ::operator(std::ostream& out, const Grid &g);
};//...omit
std::ostream& ::operator<<(std::ostream &out, const Grid &g){
int i,j;
for(i=0;i<g.gridSize;i++){
for(j=0;j<g.gridSize;j++){
if(**g.theGrid[i][j].isAliv*e*) out<<"X";
else out<<"_";
}
out<<endl;
}
return out;
}
The complier said that "isAlive" is a private member so I can't call it that way
I think the problem is at "g.theGrid[i][j].isAlive"
I tried to friend class Grid but it didnt help
You mentioned operator<< — it's most likely a free function, so it needs to be declared as friend to be able to access private members.
class Cell {
friend std::ostream& operator<<(std::ostream&, const Grid&);
// ...
};
The class member isAlive is private, so the operator didn't have the right to access it, you need to put a friend declaration in the body of Cell's definition.
class Cell {
friend std::ostream& operator<<(std::ostream&, const Cell&);
// ...
};
This line
if(**g.theGrid[i][j].isAlive) out<<"X"
Is accessing the private member 'isAlive'. I assume theGrid is a two dimensional array of Cell objects. You need a getLiving() method defined. Then use it here.
isAlive is private, declare it as public...
EDIT1:
class Cell {
public:
bool isAlive;
Update:
private members of a class are accessible only from within other members of the same class or from their friends.
protected members are accessible from members of their same class and from their friends, but also from members of their derived classes.
Finally, public members are accessible from anywhere where the object is visible.

Definition of friend class and accessor sections

When defining a class as a friend class, does it matter in which accessor section the definitions is placed, and if so does that change the members the friend has access to?
class aclass
{
private:
// friend bclass;
public:
// friend bclass;
protected:
// friend bclass;
};
class bclass
{};
Access specifiers do not apply to friend function/Class
You can declare the Friend Function or Class under any Access Specifier and the Function/Class will still have access to all the member variables(Public,Protected & Private) of that Class.
Once you place friend class/function inside a given class (say 'aclass') anywhere. It will have access to all defined members of the class (irrespective of public/private/protected); for example:
class aClass
{
public: int pub; void fun1() {}
protected: int pro; void fun2() {}
private: int pri; aClass(const aClass& o);
friend void outsider ();
};
Friend function outsider() can access pub, pro, pri, fun1, fun2; but not aClass copy constructor in this case (if it's not defined anywhere).
Friend functions aren't placed inside any accessors by convention, because by definition they aren't part of the class. You might do something like this:
class Elephants
{
//friend void notAMemberFuncion(argument 123);
public:
// member functions;
protected:
// data members;
};
The friend class/function can access all the private/protected/public members of class, which access section the friend class/function is placed doesn't make any difference.
It's suggested to put friend class/function in the public section, because friends is part of the class interface.