I'm in the proccess of learning the language and this is a noob doubt.
Is it possible to use a virtual friend function? I don't know if it's possible, I didn't even test it but it could be useful in some situations. For example, for the overloaded operator<<().
DerivedClass dc;
BaseClass &rbc = dc;
cout << rbc;
My guess is it's possible, but I'm not sure since a friend function is not implemented in the class design, and theoretically is not part of it (though in this example, conceptually it makes sense that operator<<() should be a method, but due to syntax limitations it's not possible to implement it as one).
EDIT: my concern is related with this example:
BaseClass bc;
DerivedClass dc;
BaseClass *pArr[2];
pArr[1] = bc;
pArr[2] = dc;
for (int i = 0; i < 2; i++)
cout << pArr[i];
in this array of mixed objects, I want the correct operator<<() called for each one.
Nope, friend
virtual
functions doesn't make sense at all.
friend
functions are such, that are not methods (a.k.a. member functions) and have the right to access private
/protected
members of a class
.
virtual
functions can only be member functions. You can't have virtual
non-member function.
You can make the operator<<
take a reference to a base class and then call some virtual
member function. This way, you can make the operator<<
"almost virtual" :)
For example
class A
{
public:
virtual void f() const { std::cout << "base"; }
};
class B: public A
{
public:
virtual void f() const { std::cout << "derived"; }
};
std::ostream& operator<<(std::ostream& os, const A& a )
{
a.f();
return os;
}
int main()
{
B b;
std::cout << b << std::endl;
return 0;
}
will print derived
.
Virtual Friend Function Idiom
friend functions in C++ can not be declared virtual and therefore no dynamic binding of friend functions is possible. Applying a friend function to an entire hierarchy of classes becomes awkward if an overloaded friend function is needed for every class in the hierarchy. This lack of support for dynamic binding makes it hard to justify that are in fact an extension of the class's interface. Virtual friend function idiom addresses this concern elegantly.
You need to use virtual Friend function idiom. What it says in gist is keep a virtual function in Base and let the friend function call that function. which will polymorphically call that function of Derived Class
Copying the example directly from the link
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{ ... }
};
You can solve this without friend functions, using public virtual methods only:
struct BaseClass {
virtual void print(std::ostream& os) const;
};
struct DerivedClass {
virtual void print(std::ostream& os) const;
};
std::ostream& operator<<(std::ostream& os, const BaseClass& obj) {
obj.print(os);
return os;
}
If it doesn't make sense for the print
method to be public, then the ostream& operator<<
can be declared as friend
.
Virtual Functions are something else than friend functions.
Virtual Functions are used only with use of inheritance in the program with one class as base class and other as derived classes.
Virtual functions are used for dynamic binding of objects. It means that you can store an object of derived class in a pointer of base class and still call the method of that partiular derived class. The concept is known as Polymorphism.
Friend functions are used to access the private interface of a class. They could be used even when no inheritance has been used in your class.
You can't be both a friend and a virtual function of the same class. However, a friend operator could call a virtual function from the object it is printing.
ostream& operator<<(ostream& stream, const BaseClass& rbc)
{
rbc.print_on(stream);
return stream;
}