Can't Overload operator as member function
When overloaded as a member function, a << b
is interpreted as a.operator<<(b)
, so it only takes one explicit parameter (with this
as a hidden parameter).
Since this requires that the overload be part of the class used as the left-hand operand, it's not useful with normal ostream
s and such. It would require that your overload be part of the ostream
class, not part of your class. Since you're not allowed to modify ostream
, you can't do that. That leaves only the global overload as an alternative.
There is, however, a fairly widely-used pattern where you overload the operator globally, but have that call a member function:
class whatever {
// make this public, or the global overload a friend.
std::ostream &write(std::ostream &dest) const {
// write self to dest
}
};
std::ostream &operator<<(std::ostream &os, whatever const &w) {
return w.write(os);
}
This is particularly useful when/if you want polymorphic behavior. You can't make the overloaded operator polymorphic itself, but you make the member function it calls virtual
, so it acts polymorphic anyway.
Edit: to (I hope) clarify the situation, you can do this a few different ways. The first and probably most obvious is to just make our write
member public, and have the global operator call it. Since it is public, we don't have to do anything special to let the operator use it:
class myClass {
public:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
// since `write` is public, we can call it without any problem.
return m.write(os);
}
A second alternative is to make write
private, and declare operator<<
a friend to give it access:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access:
friend std::ostream &operator<<(std::ostream &, myClass const &);
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
There's a third possibility that's almost like the second:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access.
// We also implement it right here inside the class definition though:
friend std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
};
This third case uses a rather strange (and little known) rule in C++ called "name injection". The compiler knows that a friend
function can't be part of the class, so instead of defining a member function, this "injects" the name of that function into the surrounding scope (the global scope, in this case). Even though operator<<
is defined inside the class definition, it's not a member function at all -- it's a global function.
Should operator be implemented as a friend or as a member function?
The problem here is in your interpretation of the article you link.
Equality
This article is about somebody that is having problems correctly defining the bool relationship operators.
The operator:
- Equality == and !=
- Relationship < > <= >=
These operators should return a bool as they are comparing two objects of the same type. It is usually easiest to define these operators as part of the class. This is because a class is automatically a friend of itself so objects of type Paragraph can examine each other (even each others private members).
There is an argument for making these free standing functions as this lets auto conversion convert both sides if they are not the same type, while member functions only allow the rhs to be auto converted. I find this a paper man argument as you don't really want auto conversion happening in the first place (usually). But if this is something you want (I don't recommend it) then making the comparators free standing can be advantageous.
Streaming
The stream operators:
- operator << output
- operator >> input
When you use these as stream operators (rather than binary shift) the first parameter is a stream. Since you do not have access to the stream object (its not yours to modify) these can not be member operators they have to be external to the class. Thus they must either be friends of the class or have access to a public method that will do the streaming for you.
It is also traditional for these objects to return a reference to a stream object so you can chain stream operations together.
#include <iostream>
class Paragraph
{
public:
explicit Paragraph(std::string const& init)
:m_para(init)
{}
std::string const& to_str() const
{
return m_para;
}
bool operator==(Paragraph const& rhs) const
{
return m_para == rhs.m_para;
}
bool operator!=(Paragraph const& rhs) const
{
// Define != operator in terms of the == operator
return !(this->operator==(rhs));
}
bool operator<(Paragraph const& rhs) const
{
return m_para < rhs.m_para;
}
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};
std::ostream & operator<<(std::ostream &os, const Paragraph& p)
{
return os << p.to_str();
}
int main()
{
Paragraph p("Plop");
Paragraph q(p);
std::cout << p << std::endl << (p == q) << std::endl;
}
c++ overloaded (stream extraction and insertion) operator function as member function?
- No, not for regular user defined types. The functions you made into
friend
s in your class definition are free functions:std::ostream& operator<<(std::ostream&, const PhoneNumber&);
std::istream& operator>>(std::istream&, PhoneNumber&);std::basic_ostream
does have someoperator<<
member overloads for fundamental types, such asint
, and some types defined in the standard library though. If you inherit from some of those standard types, likestd::basic_streambuf<CharT, Traits>
, you will be able to use thebasic_ostream::operator<<
member overloads for those types. - It means that you are not allowed to modify the definition of
std::basic_ostream
to addstd::basic_ostream& operator<<(const PhoneNumber&)
as a member function.
Overload operators as member function or non-member (friend) function?
Each operator has its own considerations. For example, the << operator (when used for stream output, not bit shifting) gets an ostream as its first parameter, so it can't be a member of your class. If you're implementing the addition operator, you'll probably want to benefit from automatic type conversions on both sides, therefore you'll go with a non-member as well, etc...
As for allowing specialization through inheritance, a common pattern is to implement a non-member operator in terms of a virtual member function (e.g. operator<< calls a virtual function print() on the object being passed).
operator overloading and non-member functions c++
Here is the addition operator outside of the class:
Complex operator+(const Complex& lhs, const Complex& rhs) {
//implement the math to add the two
return Complex(lhs.aGetValue() + rhs.aGetValue(),
lhs.bGetValue() + rhs.bGetValue());
}
Of course you will need to declare aGetValue()
and bGetValue()
as const
:
double aGetValue() const {return a;}
double bGetValue() const {return b;}
friend vs member functions in Operator Overloading C++
The choice isn't "member or friend" but "member or non-member".
(Friendship is frequently overused, and usually taught much too early in schools.)
This is because you can always add a public member function that a free function can call.
For instance:
class A
{
public:
explicit A(int y) : x(y) {}
A plus(const A& y) const { return A{x + y.x}; }
private:
int x;
};
A operator+(const A& lhs, const A& rhs) { return lhs.plus(rhs); }
As for how to choose: if the operator doesn't take an instance of the class as its left-hand operand, it must be a free function, otherwise it's pretty much a matter of personal taste (or coding standards if you're not alone).
Example:
// Can't be a member because the int is on the left.
A operator+ (int x, const A& a) { return A{x} + a; }
For operators that have a corresponding mutating operator (like +
and +=
), it's common to do the mutating operator as a member and the other as a non-member:
class B
{
public:
explicit B(int y) : x(y) {}
B& operator+= (const B& y) { x += y.x; return *this; }
private:
int x;
};
B operator+(B lhs, const B& rhs) { return lhs += rhs; }
but you can spell this out too, of course:
class C
{
public:
explicit C(int y) : x(y) {}
C& add(const C& y) { x += y.x; return *this; }
private:
int x;
};
C& operator+=(C& lhs, const C& rhs) { return lhs.add(rhs); }
C operator+(C lhs, const C& rhs) { return lhs += rhs; }
Why can't I access private members of class Box in operator?
The problem is that you don't have any friend declaration for the overloaded operator<<
and since l
, b
and h
are private
they can't be accessed from inside the overloaded operator<<
.
To solve this you can just provide a friend declaration for operator<<
as shown below:
class Box{
int l, b, h;
//other code here as before
//--vvvvvv----------------------------------------->friend declaration added here
friend ostream& operator <<(ostream& out, const Box& B);
};
//definition same as before
ostream& operator <<(ostream& out, const Box& B){
cout << B.l << " " << B.b << " " << B.h ;
return out;
}
Working demo
Related Topics
How to Use Windbg to Analyze the Crash Dump for Vc++ Application
A Good Example for Boost::Algorithm::Join
Converting Bool to Text in C++
Generating M Distinct Random Numbers in the Range [0..N-1]
Unresolved External Symbol Lnk2019
Linking Problems Due to Symbols with Abi::Cxx11
How to Have Static Data Members in a Header-Only Library
Are "Seekp" & "Seekg" Interchangeable
C++ Class Member Function Pointer to Function Pointer
How to Change the Variable to Which a C++ Reference Refers
Initializing a Union with a Non-Trivial Constructor
Is Volatile Bool for Thread Control Considered Wrong
How to Access Private Data Members Outside the Class Without Making "Friend"S