I am very confuse in getting the idea of operator overloading as a member and non member function.
What do we actually mean, when we overload operator as a non-member function and similarly what do we mean when we overload operator as a member functions. Although I know that the non-member functions are the friend functions.
If you overload an operator as a non-member function, you need to specify an object which you want to operate on specifically in your argument list.
If you overload it as a member function, the "this" pointer will do part of the work for you.
Consider the following example:
class Test {
public:
friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
Test operator+(const Test &rhs); // Member function
};
The difference between the two is that the non-member function doesn't have the this pointer that compiler conveniently passes for you whenever you're talking about a specific instance of a class.
The member function one has the lhs inferred, therefore you need to provide only the rhs.
Please do note that the "friend" is not necessary but if you want to access Test's private members, you need it.
Compiler can disambiguate based on the parameter count. If you wanted to declare friend Test operator+(const Test &rhs), it would complain about insufficiency of arguments because + is a binary operator. The lhs of a member function operator+ is "this".
example
class Foo {
public:
Foo operator+(Foo) // member variant
// declared inside the function
}; // end of class
Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
// could be just a call to the member variant
lhs.operator+(rhs);
// I usually do this when implementing std::stream operators,
// don't remember why just now.
}
the non-member does not need to be friended but may be if it need access to internal state.
the non-member has some advantages when it comes to templated code and namespaces on some compilers if I remember correctly, It can also be fine to friend in the non-member variant to document that there is a function outside the class that is somewhat specific to this class. It tells me that if I change that class I may have to look over the non-member operator to make sure that I have not broken anything.
A small example: (I haven't tried compiling this code but I hope it works)
class MyClass
{
public:
MyClass operator+(const MyClass& other) const; //member operator declaration
friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
int _a;
}
//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
MyClass result;
result._a = _a + other._a;
return result;
}
//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
MyClass result;
result._a = first._a - second._a;
return result;
}
Mind the differences: in the member operator definition I don't specify anything before the first _a after "=" - this->_a is assumed.
The member operator functions can be used only if an instance of your class is the first argument of the operator. If, for example you wanted to do something like 2 + myClassObject, you would need to override the non-member operator MyClass MyClass::operator+(int first, const MyClass& second) (or with whatever return value you want this to have).
Note also that I needed the friendship declaration only for my non-member operator to have an access to the private _a field.
Most operators should be defined as members.
class MyClass
{
...
public:
const MyClass& operator+=(const MyClass&);
};
Bit this is identical in behavior to the following:
class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);
The implied this in the first example is analagous to the first parameter to the second example. If the second example needs access to the internal state of MyClass, it needs to be friended.
class MyClass
{
friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);
The prototypical exception to this is operator<< on std::ostream.
std::ostream& operator<<(std::ostream&, const MyClass&);
This is logically a member of your MyClass, but because of the ordering of the parameters it would have to be a non-member of both classes or a member of std::ostream. Because you can't add members to std::ostream, this must be defined as a non-member.
Related
Is it possible for a non-member and non-friend function to achieve this?
Presume that it is a binary operator, which means we need to pass two arguments from different objects. How can it access the private members?
This is an example:
class Foo{
private:
int m_i;
public:
Foo(int i): m_i{i} {}
int get() { return m_i; }
};
Foo operator+(Foo& foo1, Foo& foo2){
return {foo1.get() + foo2.get()}; // you can not access m_i directly as you do in member functions and friend functions
}
Generally speaking, you use normal functions for operator overloading operators that don't modify the state left operand and don't need access to private or protected members directly.
Nonmember functions that are part of the interface of a class should be declared in the same header as the class itself.
The upper quote came from the book C++Primer 5th ed. I wonder if there is a best practice to distinguish nonmember functions and member functions in the header file? Or this is not necessary at all?
Or put it this way:
As a designer of a class, is it necessary to tell the user in the header file that which function is only part of the interface and which one is member function?
The language syntax already distinguishes members from non members, both for definition and declaration.
Declarations
class Example
{
public:
void member(int); // member, inside the class definition
friend std::istream & operator>>(std::istream &, Example &); // non-member, marked with keyword friend
}
std::ostream & operator<<(std::ostream &, Example &); // non-member, outside the class definition
Definitions
void Example::member(int param) {} // Example:: qualification on the name
std::istream & operator>>(std::istream & is, Example &) { return is; } // no Example::
std::ostream & operator<<(std::ostream & os, Example &) { return os; } // no Example::
You can often lay the header out in sections, and give the group a heading, but the distinction is apparent from the syntax
This question already has answers here:
Why define operator + or += outside a class, and how to do it properly?
(4 answers)
Closed 8 years ago.
Assume that I have the following basic class where I want to overload operator+:
class foo {
private:
arbitrary datatype
public:
foo() { set private data; };
virtual ~foo() {};
};
I've always used this format:
foo operator+( const foo &rhs );
However, I've recently stumbled onto some code where the person exclusively used:
friend foo operator+( const foo &lhs, const foo &rhs );
So, is it standard to use one version over the other? Are there situations where you would be forced into one version (This is only for adding the same object types)? I'm not familiar with assembly language, but would the compiler convert these into the same list of instructions (This question is obviously dependent on answers to the first 2)?
To answer your first 2 questions
It is recommended (but not enforced) to use the friend approach for binary operators because it allows to have objects that are convertible to your class on the left hand side of the operator. Consider this:
class Foo
{
// private members
public:
Foo(int) {/* ctor implementation */} // implicit convertible to int
Foo(const Foo&) { /* copy ctor implementation */ }
friend Foo operator+(const Foo& lhs, const Foo& rhs){/* implementation */}
};
Now you can do:
Foo foo1{1};
Foo foo2 = 1 + foo1; // 1 is implicitly converted to Foo here
If operator+ would have been a member function, the call above would fail (left hand side, even if convertible to Foo, will not be automatically converted by the compiler), and you'd be only able to use
Foo foo2 = foo1 + 1;
So, in conclusion, using friend for binary operators make them more "symmetric".
Last question:
The assembler would not generate the same code, as the friend/member operator+ are doing slightly different things.
See also a very good guide about overloading operators here.
In the following :
template<typename Derived>
class Base:
{
inline Derived& operator=(const Base<Derived>& x);
}
Does this declaration erases the default copy assignment operator or do I have two operators :
inline Derived& operator=(const Base<Derived>& x);
// (declared by me)
AND
inline Base<Derived>& operator=(const Base<Derived>& x);
// (declared by the compiler)
In this case, when I call the function, how the compiler will get the right operator ?
If you declare any method that can pass for an assignment operator:
XXX Foo::operator=(Foo&);
XXX Foo::operator=(Foo const&);
XXX Foo::operator=(Foo volatile&);
XXX Foo::operator=(Foo const volatile&);
then the compiler will not generate the default version Foo& operator=(Foo const&);.
Note that the return type is completely free, as for other methods. You could use void, bool, whatever really. It is just idiomatic (but not required) to return a reference to self in order to allow assignment chaining: a = b = c = 0; which itself stems from the guideline that overloaded operators should follow the semantics of their built-in counterparts.
Have you tried? Overloading by return type only would be a compile error, so my guess is that the one defined replaces the default one.
So can you overload operators to handle objects in multiple classes (specifically private members.)
For example if I wanted == to check if a private member in Class A is equal to objects in a vector in Class B.
For example:
bool Book::operator==(const Book& check){
return(((ISBN1 == check.ISBN1) && (ISBN2 == check.ISBN2) && (ISBN3 == check.ISBN3)
&& (ISBN4 == check.ISBN4)) || (title_ == check.title_));}
Everything in that overload is part of the Book class, however what if I wanted to do something like this.
if(*this == bookcheckout[i])
with bookcheckout being part of a Library class. The == would fail in trying to compare title_ to a title_ stored in a vector of the Library class.
It's odd because I have the program doing the exact same thing in two different places, but in one place it's working and in the other it isn't.
Answered: had to have the function that the operator was in be a member function of the same class that the operator was a member function of
If you make operator friend or member of one class, it will be able to access its private members. To access privates of both, operator will have to be free standing friend of both.
That is a bit unwieldy, so consider making public interface for interesting things instead.
(suppressed all puns about accessing private parts of multiple entities)
Here is how you can make a very friendly operator, but again, this is not a good solution.
(didn't compile the code)
class B;
class A
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
class B
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.private_ == b.private_;
} class B;
This is a better way -- just make public getters and use them in operator.
class A
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
class B
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.GetPrivate() == b.GetPrivate();
}
You also can make operator to be part of one of the classes, if you need privates from it alone.
Read up on operator overloading syntax for more.
You don't specify the type of bookcheckout, so I can't be sure, but I think that your operator== will work without change.
For instance, if the code is:
class Library
{
public:
const Book & operator[] (int i);
};
Library bookcheckout;
Then your if statement will call the operator== you have without a problem.
Yes. If you need to access private members, consider providing an appropriate public interface for them OR go for friend class. It is usually better to avoid it though. To handle a specific type, implement operator== with an instance of that type.
You can, but you would need to make either 'bool operator==(A a, B a)' 'friend' of class A if you are using a free function or make class B 'friend' of class A if you implement the comparison operator as a class member function.
You can avoid the friendship requirement by providing a public accessor to the private member in class A