How to provide protection to friend function in C++ - 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;
}

Related

Polymorphism with a friend function in C++

I would like to combine the concepts of polymorphism and friendship. I am making a pure virtual member function of a base class a friend of another class. I would then like to override this pure virtual member function in the classes derived from that base class, and access private member data of the class who has such function as friend. See the code snippet below. The compiler complains when I refer to my_int in the derived classes member function add(). I understand friendship is a 1-to-1 relationship, but I wonder if there is any way around it so as to implement polymorphism. Do I just have to make the member functions of the different derived classes friends of the foo() class?
class foo {
private:
int my_int{};
public:
friend virtual int base::add();
};
class base {
public:
virtual int add() = 0;
};
class derived_1 : public base {
public:
int add() {
return my_int + 1;
}
};
class derived_2 : public base {
public:
int add() {
return my_int + 2;
}
}
First, with what you've displayed it's not going to work because my_int is a member of foo but in the base class tree there is no 'foo' to get the member from.
The easy answer would be to make the function take an int argument and do away with the use of friend entirely.
struct derived2 : base
{
int add(int arg) { return arg + 2; }
};
The use of 'friend' should make you seriously question whether what you are doing is a good answer, sometimes the answer to that question is 'yes' but not often. And the more friends you need the less often the answer remains 'yes'.
Another way would be to add a function to base:
int get_arg(foo & f) { return f.my_int; }
and make that function the friend rather than add, get_arg() would be called from each derived's add() in order to get the value to work with but get_arg is not itself virtual.
You might want to look here:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Friend_Function
Intent
Simulate a virtual friend function.
Solution and Sample Code
Virtual friend function idiom makes use of an extra indirection to
achieve the desired effect of dynamic binding for friend functions. In
this idiom, usually there is only one function that is a friend of the
base class of the hierarchy and the friend function simply delegates
the work to a helper member function that is virtual. The helper
function is overridden in every derived class, which does the real job
and the friend function just serves as a facade.
class Base {
public:
friend ostream& operator << (ostream& o, const Base& b);
// ...
protected:
virtual void print(ostream& o) const
{ ... }
};
/* make sure to put this function into the header file */
inline std::ostream& operator<< (std::ostream& o, const Base& b)
{
b.print(o); // delegate the work to a polymorphic member function.
return o;
}
class Derived : public Base {
protected:
virtual void print(ostream& o) const
{ ... }
};

Remove friend class dependency in the following case

class foo
{
bar b;
someFunction()
{
b.alphaObj->someFunctionOfAlpha();
}
};
class bar
{
friend class foo;
// many more friends
private:
alpha *alphaObj;
};
How do I remove the friend dependency without exposing the private members with getters and setters.
I understand friend classes could help in enhancing encapsulation but there are a lot of friend classes defined in my class exposing the private members to all. Hence I am thinking of a better approach and any help is appreciated.
Independent of your friend issue, being required to write this
b.alphaObj->someFunctionOfAlpha();
is not the best design. You should rather call (*):
b.someFunctionOfAlpha();
Now it is also obvious how to remove the friends:
class bar
{
public:
void someFunctionOfAlpha() { alphaObj->someFunctionOfAlpha(); }
private:
alpha *alphaObj;
};
(*) This guideline has a name, I just cannot find it at the moment. In general, calling a method should be like: "Do that!". Calling a method should not be like "Show me your internals so I can do what I want".

Friend function cannot access private member variable

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.

Read private variables class members

I'm new to c++ and I need to read from private class members of a class in a method that's in a different class, for example:
class a{
private:
int x;
}
class b{
void foo();
}
void b::foo(){
//here I want to read from x that's in a
}
Do I have to set up a function in class a like int readx(){return x);) or a readclass(){return *this);}? Is there another way?
The private section of a class has the objective of 'hiding' the way you handle the data, providing a streamlined way of accesing said data with public methods.
The advantage of using a public method to change the value of private members is that you can, for example, allow values only between 0 and 10 for 'x'.
In your case, you should think about what does 'x' represent in your first class, and if it makes sense for the second class to access it directly and without any control or special consideration. If this is the case, it should probably be a public value. In the other case, you will need to make a public method to read it, like your readx example.
If only 'b' has the privilege to access 'x' directly, you can also define a friend function, like someone already said.
Note that returnig a pointer to the instance wouldn't allow access to private members of the class.
You could use friend class or function, but it is a bad idea to use private members of methods (tests are only reasonable excuse for that). Better to use public methods for that or redesign your code if you couldn't avoid usage of private members.
You can implement a friend function that can access x in foo.
Reference
If there is no accessor to this data member in class a then you should declare the member function of class b as a friend function of class a.
For example
#include <iostream>
class B
{
public:
void foo() const;
};
class A
{
public:
A( int x ) : x( x ){}
private:
friend void B::foo() const;
int x;
};
void B::foo() const
{
A a { 10 };
std::cout << a.x << std::endl;
}
int main()
{
B().foo();
return 0;
}
Declaring a friend function or class would grant read and write access to a's x to that function or class, a
class a {
public:
const int& readx() const { return x; }
private:
int x
};
or, if you like that semantics better
class a {
public:
const int& x() const { return x_; }
private:
int x_;
};
grants read access only, but to every client.

C++ friend inheritance?

Does a subclass inherit, the main class' friend associations (both the main class' own and other classes friended with the main class)?
Or to put it differently, how does inheritance apply to the friend keyword?
To expand:
And if not, is there any way to inherit friendship?
I have followed Jon's suggestion to post up the design problem:
C++ class design questions
Friendship is not inherited in C++.
The standard says (ISO/IEC 14882:2003, section 11.4.8):
Friendship is neither inherited nor transitive.
You can create (static) protected methods in the parent that will allow you to do things like that.
#include <stdio.h>
class MyFriend
{
private:
int m_member = 2;
friend class Father;
};
class Father
{
protected:
static int& getMyFriendMember(MyFriend& io_freind) { return io_freind.m_member; }
};
class Son : public Father
{
public:
int doSomething(MyFriend& io_freind)
{
int friendMember = getMyFriendMember(io_freind);
return friendMember;
}
};
int main(){
MyFriend AFriendOfFathers;
Son aSonOfFathers;
printf("%d\r\n", aSonOfFathers.doSomething(AFriendOfFathers));
return 0;
}
This however bypasses encapsulation so you probably should take a second look at your design.
friend only applies to the class you explicitly make it friend and no other class.
http://www.parashift.com/c++-faq-lite/friends.html#faq-14.4
The answer is very simple: no, subclasses do not inherit friend associations. A friend can only access the private members of the class the association is declared in, not those of parents and/or children of that class. Although you might be access protected member of a superclass, but I'm not sure about that.