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.
Related
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.
I have two classes, base and derived. In main I have a vector which is *base type and contains one base object and one derived object. I have overloaded output operator for both classes, but when I print the vector for derived class, base output operator is called although I have overloaded it separately. What should I change in my program to change output from:
12
30
to
12
30 31
?
This is the code:
#include <iostream>
#include <vector>
using namespace std;
class base {
int x;
public:
base(int _x) : x(_x) {}
friend ostream& operator<<(ostream& out, base obj) {
return out << obj.x;
}
};
class derived : public base {
int y;
public:
derived(int _x, int _y) : base(_x), y(_y) {}
friend ostream& operator<<(ostream& out, derived obj) {
return out << (base) obj << ' ' << obj.y;
}
};
int main() {
vector<base*> vec;
base* a = new base(12);
derived* b = new derived(30,31);
vec.push_back(a);
vec.push_back(b);
for (auto p: vec) cout << *p << '\n';
}
Dynamic dispatch, based on the underlying object, works only for virtual member functions. It does not work for non-member functions or non-virtual member functions.
One way to get around the problem would be:
Use the friend function using the base type.
Change the argument type for obj to be a const reference.
From that function, call a virtual member function to do the real work.
class base {
int x;
public:
base(int _x) : x(_x) {}
virtual std::ostream& write(std::ostream& out) const
{
return (out << x);
}
// Change obj to be a const reference
friend std::ostream& operator<<(std::ostream& out, base const& obj)
{
return obj.write(out);
}
};
class derived : public base {
int y;
public:
derived(int _x, int _y) : base(_x), y(_y) {}
virtual std::ostream& write(std::ostream& out) const
{
// Let the base class take care of its part.
base::write(out);
// Now take care of this class part.
return ( out << ' ' << y);
}
// This is useless now.
// friend ostream& operator<<(ostream& out, derived obj) {
// return out << (base) obj << ' ' << obj.y;
// }
};
PS Why is "using namespace std;" considered bad practice?
Yes I know that private modifier created in order to prohibit access to class data
but isn't friend intended to allow special access to it?
Compiler:
main.cpp: In member function 'void C::blah(B&)':
main.cpp:48:26: error: 'int B::a' is private within this context
std::cout << obj.a << std::endl;
Everything below is implemented the way as it is in many tutorials.
May be it's just a silly mistake I made and blind to spot.
class C;
class B {
private:
int a = 2;
public:
friend void blah(B& obj);
};
class C {
public:
void blah(B& obj) {
std::cout << obj.a << std::endl; //*
}
};
*Member B::a is inaccessible
You're declaring a non-member function named blah, but not C::blah as friend.
You could change your code to the following, and note the order of the declaration and definition.
class B;
class C {
public:
void blah(B& obj);
};
class B {
private:
int a = 2;
public:
friend void C::blah(B& obj);
};
void C::blah(B& obj) {
std::cout << obj.a << std::endl;
}
LIVE
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);
}
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.