Does friend functions must be defined in header files? [duplicate] - c++

Im trying to define a class friend function outside the namespace like this:
namespace A{
class window{
private:
int a;
friend void f(window);
};
}
void f(A::window rhs){
cout << rhs.a << endl;
}
Im getting an error said that there is ambiguity. and there is two candidates void A::f(A::window); and void f(A::window). So my question is :
1) How to make the global function void f(A::window rhs) a friend of the class A::window.
EDIT: (After reading the answers)
2) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?
3) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not a defined inside a namespace it's okey for the function to be declared after the function is declared a friend.

As well as adding a :: you need to forward declare it, e.g.:
namespace A { class window; }
void f(A::window);
namespace A{
class window{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs){
std::cout << rhs.a << std::endl;
}
Note that for this forward declaration to work you need to forward declare the class too!

This should do it: you need forward declares to make it clear f is in the global namespace (and not file static):
#include <string>
#include <iostream>
using namespace std;
////// forward declare magic:
namespace A{ class window; }
void f(A::window rhs);
//////
namespace A {
class window {
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs) {
cout << rhs.a << endl;
}
int main()
{
}

Using ::, you can also friend a class from the outer wrapping namespace:
namespace Na {
class A;
namespace Nb {
class B {
...
friend class ::Na::A;
};
Without going from global top as 'friend class Na::A', the search will be done in Na::Nb::Na only.

Related

Difference between friend function and getters

I'm currently new to OOP concepts of C++ language like friend of the function and friend of the class .
May be this is not he best comparision between freinds and getters but for the example below:
#include <iostream>
using namespace std;
class ClassB; // forward declaration
class ClassA
{
int numA;
friend int add(ClassA, ClassB); // friend function declaration
public:
ClassA() : numA{12} {} // constructor to initialize numA to 12
};
class ClassB
{
int numB;
friend int add(ClassA, ClassB); // friend function declaration
public:
ClassB() : numB(1) {}
};
// access members of both classes
int add(ClassA objectA, ClassB objectB)
{
return objectA.numA + objectB.numB;
}
int main()
{
ClassA objectA;
ClassB objectB;
cout << "Sum: " << add(objectA, objectB);
return 0;
}
what if i simply use getter to get the values and add them. The main moto of friend function is to access the private and public data members (i guess) , and getters are already doing this .
I'm quite confused here.
There is an excellent talk about this subject here: CppCon 2017: Klaus Iglberger “Free Your Functions!”
My take-away is that if a member function needs no access to the internals of a class, then it should not be a member function. In your case, how will Class A be usable? It is not right now, but I imagine you will have something like explicit operator int() const or int get_val() const. You can simply use this in a free function:
A operator+(A lhs, B rhs) {
return A{lhs.get() + rhs.get()};
}
B operator+(B lhs, A rhs) {
return B{lhs.get() + rhs.get()};
}
int main() {
...
cout << "sum: " << (objectA + objectB).get() << "\n";
...
Or something similar.

Why do I get an error with my usage of C++ friend functions?

I'm trying to learn friend function in C++, despite defining display() as a friend function, it's unable to access variable a and b. That's why compiler is showing error.
Who is display supposed to display? Being friend just means that if you run across an object of that class you can access all its innards. You probably want:
void display(const Add &a) {
cout << a.a + a.b;
}
And then you can call it in main with:
display(A);
(remember you'll need to change the definition of display in the class too!)
For better explanation friend function is for accessing private or protected attributes of the class from outside (that it shouldn't reach without proper accessors). A better explaining answer can be found at
Example taken from programiz:
#include <iostream>
using namespace std;
// forward declaration
class B;
class A {
private:
int numA;
public:
A(): numA(12) { }
// friend function declaration
friend int add(A, B);
};
class B {
private:
int numB;
public:
B(): numB(1) { }
// friend function declaration
friend int add(A , B);
};
// Function add() is the friend function of classes A and B
// that accesses the member variables numA and numB
int add(A objectA, B objectB)
{
return (objectA.numA + objectB.numB);
}
int main()
{
A objectA;
B objectB;
cout<<"Sum: "<< add(objectA, objectB);
return 0;
}
on normal cases that add function out of the classes shouldn't reach numA or numB attributes since they are private but since it is declared as friend it gives no error. So on your problem you should do it like this:
#include<iostream>
using namespace std;
class Add {
private:
int a, b;
/*Declared as private to show the significance of friend otherwise
*it does not make sense*/
public:
void get_data();
friend void display(Add);
}
//And change the display function
void display(Add obj) {
cout << (obj.a + obj.b);
}

Making member function, friend of a class

I've been trying to write up a code to implement a member function that could access private data of a class by declaring it as a friend within the class. But my code is failing and I can't seem to figure out what's wrong with it:
#include <iostream>
using namespace std;
class A;
class B
{
private:
int b; // This is to be accessed by member function of A
public:
friend void A::accessB();
};
class A
{
private:
int a;
public:
void accessB();
};
void A::accessB()
{
B y;
y.b = 100;
cout << "Done" << endl;
}
int main(void)
{
A x;
x.accessB();
}
I am trying to access the private contents of B making use of getAccessB function which is member function of A. I have declared it as a friend. What's wrong with this?
A::accessB is not declared at the point of the friend declaration, so you can't refer to it. You can fix this by shifting the order of definitions and declarations such that A::accessB is visible to B:
class A
{
private:
int a;
public:
void accessB();
};
class B
{
private:
int b;
public:
friend void A::accessB();
};
void A::accessB()
{
B y;
y.b = 100;
cout << "Done" << endl;
}
Note that making a function a friend just so that it can modify your private state is a bad code smell. Hopefully you are just doing this to understand the concepts.
The ordering. If you are referring to A::accessB, A must be declared by that point. Place the A class above the B, and it will work fine.

Class Access Variable

I've written out a template of what the basic code I'm trying to figure out is based on so you don't need to sift through it
#include <iostream>
using namespace std;
class class1 {
int main()
{
return 0;
}
If you need to do it the the exact declaration order in your post you can do this with a forward declaration. This will allow you to declare accessclass2 to take an instance of class2 as an argument without knowing the details. You will simply need to define accessclass2 after class2 has been defined.
#include <iostream>
using namespace std;
// Forward declaration allows you to pass a reference to the function withing
// having the details of the class2 yet.
class class2;
class class1
{
public:
int x;
class1()
{
x = 0;
}
void accessclass2(class2& other);
};
class class2 {
public:
int y;
class2()
{
y = 10;
}
void print()
{
cout << y << endl;
}
};
void class1::accessclass2(class2& other)
{
other.print();
}
int main()
{
class1 foo;
class2 bar;
foo.accessclass2(bar);
return 0;
}

Friend function that takes 2 classes in parameters - 'Class' not defined

I encountered some issues while working on friend functions. I want to use a friend function that uses two different classes in parameters. Here is the sample of code:
ObjectA.h:
#ifndef OBJECTA_H_
#define OBJECTA_H_
#include "ObjectB.h"
#include <iostream>
using namespace std;
class ObjectA {
private:
friend void friendFunction(ObjectA &,ObjectB &);
public:
ObjectA();
virtual ~ObjectA();
};
#endif /* OBJECTA_H_ */
ObjectB.h:
#ifndef OBJECTB_H_
#define OBJECTB_H_
#include <iostream>
using namespace std;
#include "ObjectA.h"
class ObjectB {
private:
friend void friendFunction(ObjectA &, ObjectB &);
public:
ObjectB();
virtual ~ObjectB();
};
#endif /* OBJECTB_H_ */
Both .cpp files for ObjectA and ObjectB are empty (empty constructor and destructor). Here is the main .cpp file:
#include <iostream>
using namespace std;
#include "ObjectA.h"
#include "ObjectB.h"
void friendFunction(ObjectA &objA, ObjectB &objB){
cout << "HIIIIIIIIIII";
}
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
This all thing sends me the following error :
'ObjectA' has not been declared
And this error is pointing to this line in the ObjectB.h :
friend void friendFunction(ObjectA &, ObjectB &);
As you can see, the ObjectA.h file has been included in the ObjectB.h file. So I don't know where my error come from.
Maybe I'm using friend function in a wrong way ?
Thank you guys !
In ObjectA.h, replace:
#include "ObjectB.h"
with:
class ObjectB;
Make the corresponding change in ObjectB.h.
What's happening is that main.cpp is including ObjectA.h. Before declaring the ObjectA class, ObjectA.h includes ObjectB.h. When ObjectB.h tries to include ObjectA.h again, the #ifndef OBJECTA_H_ test fails, meaning the ObjectA class isn't declared when the friend function is declared, leading to the error.
You can break this loop in your specific case by using a forward class declaration instead of #include.
Baybe using template function instead? But this way you will break encapsulation.
class A{
private:
template<typename T, typename B>
friend void friendFunc( const T&, const B&);
int m_a;
};
template<typename A, typename B>
void friendFunc( const A& a, const B& b){
std::cout << a.m_a << std::endl;
}
int main(int argc, char **argv) {
friendFunc<A, int>(A(), int(3));
return 0;
}