Virtual functions cannot be friends - c++

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.

Related

C++: Function call precedence rules for calling functions on objects of derived classes?

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.

Virtual-like friend functions?

I want to create interface like
class Scalar {
public:
Scalar() {}
virtual ~Scalar() {}
//virtual members operators
virtual Scalar& operator+() const = 0;
virtual const Scalar operator-() const;
virtual Scalar& operator=() = 0;
virtual Scalar& operator+=() = 0;
//...
};
I intend also to use some friend functions, for example:
friend const Scalar operator+(const Scalar&, const Scalar&);
But there is a problem when I derive the abstract class, and create derived class, say:
class RealNumber: public Scalar {
public:
friend const RealNumber operator+(const RealNumber&, const RealNumber&);
//some definitions...
};
According to this logic, I would need to define a new overload of friend operator+ for every new class derived from Scalar. Is there some way to solve this problem and avoid declaring these friends in all the derived classes?
Is this your problem ?
I understand that your problem is that your two friends refer to totally different functions, since they have a different signature:
friend const Scalar operator+(const Scalar&, const Scalar&);
friend const RealNumber operator+(const RealNumber&, const RealNumber&);
Worse, the choice of a class external friend will not be polymorphic: the right friend will be chose based on the compile-time type.
How to solve it ?
First of all, instead of using an outside overloaded friend, you could consider overriding the operator of the class itself (keeping the signature identical).
However this has two major challenges:
it is almost impossible to return a reference from arithmetic operator, unless you'd accept side-effects, which would then make your operator behave differently than expected.
you'd need to cope with combining different kind of scalars: what if you'd have to add a Scalar to a RealNumber ? This would require a double dispatch to be implemented to cope with all the possible combination.
So, dead-end ?
No, there are two other alternatives, depending on your real problem:
Do you really want to combine arithmetic type dynamically at run-time ? If yes, you need to go away from the C++ operator overriding approach, and implement an expression evaluator, using the interpreter pattern.
If not, consider to use a template based design, so that the compiler choses at compile-time the appropriate specialisation.
Or suffer with the many possible friends and their combination of parameter types.
You may not be able to create virtual friend functions, but you can create virtual operators (even operator + could be done this way).
Consider the following code: WARNING: THIS IS NOT GOOD DESIGN AT ALL
#include <iostream>
using namespace std;
class AA {
private:
int a;
public:
AA(int a): a(a) {};
inline int getA() const { return a; };
virtual AA operator +(const AA &a) {
AA res(this->getA() + a.getA());
return res;
}
};
class BB: public AA {
public:
BB(int a): AA(a) {}
virtual AA operator +(const AA &a) {
AA res(this->getA() - a.getA());
return res;
}
};
int main() {
BB tmp(1);
AA& a = tmp;
AA b(7);
cout << (a + b).getA();
return 0;
}
When I was writing this code, I found that a lot of flaws could be induced (like the + operator that really does substraction instead, also what if the second operand was BB instead of the first one ??)
So, about your problem, you want Scalars. So you can do the following approach:
#include <iostream>
using namespace std;
// Here, Scalar acts as an abstract class, all its goal is to convert your
// class type into some calculable value type (e.g. you can use T as double)
template <typename T>
class Scalar {
public:
// Converter function is abstract
virtual operator T() = 0;
};
class AA: public Scalar<double> {
private:
double a;
public:
inline double getA() {return a;};
AA(double a): a(a) {}
// Implements the converter function in Scalar, T in scalar is mapped
// to double because we did Scalar<double>
virtual operator double() {
return a;
}
};
class BB: public Scalar<double> {
private:
int a;
public:
inline double getA() {return (double)a;};
BB(int a): a(a) {}
virtual operator double() {
return (double)a;
}
};
int main() {
BB tmp(1);
AA b(7);
// Here, it is easy for us just to add those, they are automatically converted into doubles, each one like how it is programmed.
cout << (b + tmp);
return 0;
}

Friend class definition

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.

C++ enforce conditions on inherited classes

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.

Operator Overloading for Objects in Multiple Classes

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