Today I looked into the header source code of boost::asio::ip::address and found the following lines:
class address
{
// I removed some irrelevant lines here...
public:
/// Compare addresses for ordering.
friend bool operator>=(const address& a1, const address& a2)
{
return !(a1 < a2);
}
};
Now I know what friend is for but I had never seen it followed by a definition, inside a class definition.
So my question is, what does this friend declaration do ? It seems to me that operator>= is not a method here, however there is no static keyword either.
Does friend replace static in this particular case ?
Yes and no. It doesn't replace static because you don't need to qualify the name when you call the operator. It kind of does as you don't need a class instance to call it on.
It's like declaring the operator outside the class:
class address
{
// I removed some irrelevant lines here...
public:
/// Compare addresses for ordering.
friend bool operator>=(const address& a1, const address& a2);
};
inline bool operator>=(const address& a1, const address& a2)
{
return !(a1 < a2);
}
You can access private and protected methods from the class.
Think of overloading the stream operator inside the class, the same technique can be applied.
Related
I have a class Iterator, for which I have defined various operator overloads for equality testing (<, <=, >, >=, == and !=) as friend functions. Prototype example:
friend bool operator<(const Iterator &A, const Iterator &B);
class RevIterator inherits (virtually) from Iterator. Naturally, I have had to overload the operators <, <=, > and >= for this class (as friend functions again). Prototype example:
friend bool operator<(const RevIterator &A, const RevIterator &B);
I also have a class ConstIterator which inherits (virtually) from Iterator, for which I have not defined more operator overloads (they are meant to behave in the same way as for Iterator).
Finally, I have a class ConstRevIterator which inherits from RevIterator and ConstIterator, for which I have not defined any operator overloads.
Visual class hierarchy:
class Iterator {};
class RevIterator : virtual public Iterator {};
class ConstIterator : virtual public Iterator {};
class ConstRevIterator : public RevIterator, public ConstIterator {};
My assumption was that for the operator <, for example, operating on two ConstRevIterators, the function available for one of the parent classes, RevIterator (2nd func. prototype above) would be called, instead of the function for the grandparent class, Iterator (1st func. prototype above).
In summary, what are the rules for which function gets called on a reference to a 'grandchild' object, when there are functions available for its parent and grandparent classes?
Your assumption seems correct. You may find rules of overload resolution here https://en.cppreference.com/w/cpp/language/overload_resolution
Here is the part concerning your question:
If Mid is derived (directly or indirectly) from Base, and Derived is derived (directly or indirectly) from Mid
a) Derived* to Mid* is better than Derived* to Base*
b) Derived to Mid& or Mid&& is better than Derived to Base& or Base&&
c) Base::* to Mid::* is better than Base::* to Derived::*
d) Derived to Mid is better than Derived to Base
e) Mid* to Base* is better than Derived* to Base*
f) Mid to Base& or Base&& is better than Derived to Base& or Base&&
g) Mid::* to Derived::* is better than Base::* to Derived::*
h) Mid to Base is better than Derived to Base
I also produced some code to verify it:
https://godbolt.org/z/bc47dzxvY
In summary, what are the rules for which function gets called on a reference to a 'grandchild' object, when there are functions available for its parent and grandparent classes?
The answer here depends on what you mean by a "reference to a 'grandchild' object".
These will be statically bound, so if you have something like:
void foo(Iterator &a, Iterator &b) {
if (a != b) // ...
}
...it'll use bool operator!=(const Iterator &, const Iterator &) to do the comparison, even if the iterator you pass is a ConstIterator, RevIterator or ConstRevIterator.
On the other hand, if you have a function something like:
void bar(ConstRevIterator &a, ConstRevIterator &b) {
if (a != b) // ...
}
Now, since you've directly specified that it's a reference to a ConstRevItertor, it'll use bool operator!=(const ConstRevIterator &, const ConstRevIterator &) to do the comparison.
If you want virtual behavior, so the behavior depends on the actual type passed rather than the type declared for the parameter, you'll typically something more like this:
class Iterator {
protected:
virtual bool isEq(Iterator const &other) const {
// implement test for equality
}
virtual bool isNeq(Iterator const &other) {
return !(isEq(other));
}
// and so on for the other comparisons
friend bool operator==(Iterator const &a, Iterator const &b) {
return a.operator==(b);
}
// and likewise for the other comparisons
};
class ConstIterator : public Iterator {
protected:
bool isEq(ConstIterator const &other) const override {
// ...
}
bool isNeq(ConstIterator const &other) const override {
// ..
}
// and so on
};
In this case, you define virtual member functions to do the real comparisons, friend functions that take references to the base class, and invoke the virtual member functions do to the real comparison, so you'll get virtual dispatch, and the comparison will be done for the most derived type.
This has a bit of a problem though: all the functions get virtual dispatch, which can be on the slow side, especially for something as simple as comparing two iterators--virtual dispatch could easily take longer than the comparison itself.
I wish to create an interface for a class C which has this function:
friend bool operator==(const C& a, const C& b);*
I wish to the create a mock for C for test driven purposes.
I tried doing it like this:
class IC
{
virtual friend bool operator==(const IC& a, const IC& b) = 0;
};
What should I do?
operator == is a binary operator. To make it virtual, it must be a class member.
class IC
{
virtual bool operator==(const IC& b) = 0;
};
In this case, the first argument to == is implicitly this.
Your declaration is about a free function, not a class member.
EDIT: As suggested in the comments, you should avoid this and rather implement a compare function or similar.
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.
I would like to define an abstract base class X and enforce the following:
a) every concrete class Y that inherits from X define a constructor Y(int x)
b) it should be possible to test whether two Y objects are equal.
For a, one not very good solution is to put a pure virtual fromInt method in X
which concrete class will have to define. But I cannot enforce construction.
For b), I cannot seem to use a pure virtual method in X
bool operator == (const X& other) const =0;
because in overridden classes this remains undefined. It is not enough to define
bool operator == (const Y& other) const { //stuff}
because the types don't match. How do I solve these problems?
You can force construction by making the no argument constructor private and having a public single int argument constructor in your base class. As long as the base class has some pure virtual methods, then your subclasses must call that constructor.
As for the operator==, try defining
bool operator == (const BaseClass& other) const { .. };
in all of your subclasses. Worst case, you can define a public equals(const BaseClass& other) method that is pure virtual in your base.
EDIT: the forcing constructor thing is not entirely true. What I suggested forces sub classes to call the single argument constructor. They could have a no argument constructor that passes a constant up to the base in constructor.
There's an easy solution.
// Class X
// (... some documentation ...)
//
// ** NOTE: All subclasses of X must have a constructor that takes a single int,
// ** and overload operator==.
class X {
...
For b), you can define virtual bool operator == (const X & other) const = 0 in X.
You can't have const Y & other as the parameter in the comparison, but Ys will be automatically casted to Xs and then you can use dynamic_cast to see if it's a class that you can compare with.
a - should be possible if you use CRTP and an intermediary, friend, templated subclass that all user code must inherit from. Something like so:
struct X
{
virtual bool compare(X const&) const = 0;
private:
X();
template < typename T >
friend struct client_base; // don't recall the correct code here.
};
template < typename Sub >
struct client_base : X
{
// use boost::concepts to verify Sub has Sub(int)
Sub() : X() {}
};
struct Y : client_base<Y>
{
Y(int);
bool compare(X const& x)
{
if ((Y* other = dynamic_cast<Y*>(x)) && *other == *this) return true;
return false;
}
};
Obviously I've left a lot for you to figure out to make this a complete solution.
a) doesn't have a sense as for me but you can create something
template< typename T >
Base* create( int x )
{
return T::create( x );
}
for b) ask google about "multi methods" implementation in c++
Enforcing to be constructible from an integer does not make any sense: each derived class is free to define its constructors as it wishes. You can however enforce them to pass an integer to the base class... not that it makes much more sense anyway.
The operator== is also contorted, you can however get the essence of it:
class Base
{
public:
bool operator==(const Base& rhs) const;
bool operator!=(const Base& rhs) const { return !(*this == rhs); }
private:
virtual bool equals(const Base& rhs) const = 0; // will pass only objects
// of the same dynamic type
};
bool Base::operator==(const Base& rhs) const
{
return typeid(*this) == typeid(rhs) && this->equals(rhs);
}
bool Derived::equals(const Base& rhs) const // We KNOW Base is actually a Derived
{
return *this == static_cast<const Derived&>(rhs);
}
You could try and prettify it a bit by using templates and CRTP, but what if Derived was inherited from ? it would not hold.
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