Friend function and implementation - c++

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.

Related

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.

How do I access a variable in member function #1 in member function #2?

I'm starting to work with friends of classes.
Here I have two functions called setMaxSickDays and getMaxSickDays.
I made a variable called maxSickDays in setMaxSickDays that I'd like to access from getMaxSickDays.
class timeOff
{
public:
void setMaxSickDays(numDays &friendlyObject) {
int maxSickDays;
friendlyObject.hours = 240;
maxSickDays = friendlyObject.hours;
}
void getMaxSickDays(numDays &friendlyObject) {
cout << maxSickDays;
}
};
The error: 'maxSickDays' was not declared in this scope
This may seem silly but I'm a beginner. Thanks!
You make maxSickDays a data member of your class.
class timeOff
{
public:
void setMaxSickDays(int days);
int getMaxSickDays();
private:
int maxSickDays;
};
You can't access another function's local variable, even as friend. friend is used to granted to access members (i.e. member variables or functions) of the class.
See friend declaration
The friend declaration appears in a class body and grants a function or another class access to private and protected members of the class where the friend declaration appears.

Definition of friend inside class

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

enclosing scope

what's wrong with this code?
class matrix{
private:
friend transpose(const matrix&);
friend class invert;
public: //...
};
matrix (*p)(const matrix&)=&transpose; //error: no transpose() in scope.
what does the statement means "a friend declaration does not introduce a name into enclosing scope".This problem does not occur when friend keyword is removed
The difference between the declaration of transpose() as a friend and without the friend declaration is that if you declare "friend transpose()" all you are doing is telling the compiler that a function friend with the signature shown in the friend declaration can have access to the private members of an object of type matrix. It does not declare a function transpose() with this signature - you still have to do this outside the scope of the matrix class.
If you remove the 'friend' keyword, you are declaring a member function transpose() inside the class matrix, so the compiler actually has seen a function it can take the address of.
§7.3.1.2 [namespace.memdef] p3
[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]
See also this question of mine.
Friend functions are functions that are not members of a class but
they still have access to the private members of the class.
I should point out that a friend function declaration
may be placed in either the private section or the public section,
but it will be a public function in either case, so it is clearer to
list it in the public section.
class MyClass
{
private:
int data;
public:
MyClass(int value);
friend void myFriend(MyClass *myObject);
};
void myFriend(MyClass *myObject)
{
cout << myObject->data<< endl;
}
MyClass::MyClass(int value)
{
data = value*2;
}
int main()
{
MyClass myObject(3);
myFriend(&myObject);
}
So, you need to define the friend function after you declare it.

Why can't I change a private member of a class from a friend class in a different namespace?

I am finding trouble accessing a private member of a class from a friend class.
The class that holds the private member I want to change and the class where the change is made are in different namespaces.
The friend class is defined after the class holding the data, so I've tried to forward declare the friend class outside the namespace.
g++ says that I can't modify the member because it's private, visual studio seems to think it's fine.
Am I doing some weird non-standard thing here? Why can't I change the member? Here is a simplified snippet that represents my problem:
struct S;
namespace N
{
class A
{
int m;
public:
A():m(5){};
friend struct S;
};
}
using namespace N;
struct S
{
A& a;
S(A& a):a(a) {}
void changeA(){ a.m = 9; }
};
int main()
{
A a;
S s(a);
s.changeA();
}
friend struct ::S;
what you are really doing with
friend struct S;
is declaring as friend the class N::S (which is defined nowhere).
Edit: To back up my idea that gcc behavior is correct and VC++ has a bug.
7.3.1.2/3
If a friend declaration in a non-local class first declares a class or
function the friend class or function is a member of the innermost
enclosing namespace. [...] When looking for a prior declaration of a
class or function introduced by a friend declaration, scopes outside the
innermost enclosing namespace scope are not considered.
Because friend struct S; declares N::S class but you need ::S class.
Try writing out friend struct ::S;.
At the moment, the non-existent N::S is assumed. This fix specifies the global namespace, a bit like how the leading / on a Linux path specifies the filesystem root.