C++ operator overloading or redefine? - c++

I want to overload + for Point+Point and Point+vector
class Vector
{
public:
double x;
double y;
double z;
};
class PointBase
{
public:
double x;
double y;
double z;
PointBase operator+(const Vector &vec) const
{
PointBase b;
b.x=vec.x+this->x;
b.y=vec.y+this->y;
b.z=vec.z+this->z;
return b;
}
};
class Point:public PointBase
{
public:
PointBase operator+(const Point &point) const
{
PointBase b;
b.x=point.x+this->x;
b.y=point.y+this->y;
b.z=point.z+this->z;
return b;
}
Point(PointBase& base)
{
}
Point()
{
}
};
int main()
{
Point p;
Vector v;
p=p+v;
return 0;
}
PointBase operator+(const Point &point) const hides PointBase operator+(const Vector &vec) const, why? I expect that 2 overloads work correctly: point+vector and point +point.

The operator+ in Point hides the one inherited from PointBase. To make it available, use
class Point:public PointBase
{
public:
using PointBase::operator+; // <-- here
PointBase operator+(const Point &point) const
// rest as before
Note, however, that the next problem you'll run into is that
p=p+v
attempts to use an operator= that takes a Point on the left and a PointBase on the right and that does not exist.
The reason that the operator+ in the derived class hides the one in the base class is the way name lookup works in C++: The compiler goes outward in layers (concrete class -> base class -> base base class -> ..., and for non-member functions called from a member function continues through the surrounding namespaces1) until it finds a matching name, tries to apply it, and fails if that doesn't work. You can see the same mechanism at work in this non-compiling piece of code:
void foo(char const *) { }
namespace bar {
void foo(int) { }
void baz() {
// does not compile: bar::foo hides ::foo
foo("hello");
}
}
In the case of your classes, the compiler looks in Point, finds a matching name, tries to apply it, and complains when it fails. It does not continue to look in the surrounding scope (PointBase), but it would continue to look if it had not found the operator+ in Point.
1 There's an asterisk for class templates that inherit other class templates here, where different mechanisms come into play. See Why do I have to access template base class members through the this pointer? for details, although none of that comes into play in your case.

Related

Another issue with specialised pure virtual template function (undefined reference)

As a beginner, I have some problem regarding templates, inheritance and pure virtual functions.
Consider the following, where Probability is an abstract template instantiated as RationalProbability.
Probability.h:
template <class T>
class Probability
{
public:
T value;
//Operator overloading for +
virtual Probability<T>* operator+(const Probability<T>& p);
T getValue() const { return value; }
protected:
Probability(T val) {
value = val;
}
~Probability() {};
};
Probability.cpp : empty
RationalProbability.h:
#include "Probability.h"
class RationalProbability: public Probability<float>
{
public:
RationalProbability(float prob);
virtual ~RationalProbability();
RationalProbability* operator+(const RationalProbability& p);
};
RationalProbability.cpp:
#include "RationalProbability.h"
RationalProbability::RationalProbability(float prob): Probability(prob) {}
RationalProbability::~RationalProbability()
{
}
RationalProbability* RationalProbability::operator+(const RationalProbability& p) {
RationalProbability* rp = new RationalProbability(p.getValue() + this->value);
return rp;
}
I get the following error:
Error:undefined reference to
Probability<float>::operator+(Probability<float> const&)
It is true that there is no function with that exact signature, but RationalProbability implements the template exactly with
RationalProbability: public Probability<float>
If you want a base class to have an abstract function (a virtual function you don't implement) you should say so:
virtual Probability<T>* operator+(const Probability<T>& p) = 0;
The = 0 is what tells the compiler that the member function is an abstract method that must be overridden by sub-classes.
If you don't have that, there must be a definition (implementation) of all virtual functions.
If you look closer at the error message it says that it's Probability<float>::operator+ that is missing, not RationalProbability::operator+.
I also suggest you read and check some canonical operator implementations, especially for the binary arithmetic operators, because you should not return a pointer from the operator+ function. It should return an object by value. Otherwise, how would something like a + b + c work if suddenly the result of one addition was a pointer?

Inherited functions to return Derived class, not Base class

Is it possible in C++ to formulate functions in the Base class that return Base type such that in the Derived class, they return Derived type, without overloading?
Minimal example:
class Base
{
public:
Base(double v)
{
value = v;
}
Base add(Base b)
{
return Base(b.value + this->value);
}
void print()
{
std::cout << value << std::endl;
}
double value;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v)
{
}
void timesTwo()
{
value *= 2.0;
}
};
int main()
{
Derived d1(1), d2(2);
// This doesn't work because the result is of type Base
(d1.add(d2)).timesTwo();
return 0;
}
Motivation
In the actual example, Base represents a linear algebra matrix, and Derived represents a vector. The matrix offers many functions that are all applicable to vectors, such as addition or multiplication by a scalar.
In this case, it would be desirable not having to override all these matrix functions manually to return vectors. I would like to, if possible, express that whatever this type is, the return type should be identical to it.
Example:
class Matrix
{
...
Matrix operator*(double x);
};
class Vector : Matrix
{
...
};
Matrix M;
M = M * 2.0; // works
Vector v;
v = v * 2.0; // does not work, because v * 2.0 returns a Matrix
The effort for overriding e.g. operator*() for all derived classes is increased by the fact that there are derived classes for 3- and 2-dimensional vectors, etc.
I understand that a solution is to define a cast from Matrix to Vector (and to Vector3, Vector2, ...) but this would involve copying all entries (which are, for efficiency, stack arrays).
Is there a more efficient solution? And, if not, would it generally be considered cleaner/better to
duplicate all the relevant code in each derived class, or to
define a cast?
In my current understanding, the conflicting problems are:
Duplicate code makes the solution error-prone and more difficult to refactor.
Reusing existing code requires lots of copy operations every time the "scope" changes between Matrix, Vector, Vector3, ... . Would be inefficient if used in large calculations.
Any suggestion would be most appreciated. Thanks!
Yes, but only with free functions (including most operators).
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend X& operator+=(X&x, Y&& rhs)
{
x.value += rhs.value;
return x.
}
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend std::decay_t<X> operator+(X&&x, Y&& rhs) {
auto r=std::forward<X>(x);
r+=std::forward<Y>(rhs);
return r;
}
Now if I did that right,
(d1+d2).timesTwo();
works.
I also implemented + in terms of += because that usually works well.
The fancy enable if exists because koenig lookup with very generic template operators causes strange things to happen when you pass Base and types derived from Base to template types and proceed to use + on the resulting type. By saying "only things derived from Base", the right thing happens.
We need to use a template free friend function so we can get the type of "*this" (as it where) within the template to change our return type. This cannot be done in a template member function.
The enable_if clause does not work well in MSVC, but is best practice in other compilers. For MSVC use class=enable_if instead of enable_if=0. The reason why the =0 is best is out of scope here.
Make class Base abstract and put its methods in separated functions. Also declare pure virtual the methods you need in derived classes:
#include <iostream>
class Base
{
public:
Base(double v) : value(v) {}
double value;
virtual void timesTwo() = 0;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v) {}
void timesTwo()
{
value *= 2.0;
std::cout << "timesTwo " << value << std::endl;
}
};
template <class T>
T add(const T& t1, const T& t2)
{
return T(t1.value + t2.value);
}
int main()
{
Derived d1(1), d2(2);
add(d1, d2).timesTwo();
return 0;
}

C++ virtual function override

I have a class that contains the following virtual method:
struct point {
template<typename T>
virtual typename std::enable_if<std::is_base_of<point, T>::value, double>::type distTo(T &other) const = 0;
};
The above doesn't work because:
error: templates may not be ‘virtual’
The plan is to specialize the class by making more specific instances of it like point2D, point3D. However, I only want the function to work with types of the same class. So if point2D where to inherit this class, the method distTo should only take parameter of type point2D. How can I accomplish this?
This is what I had tried before I did the above:
virtual double distTo(point& other) = 0;
But when I override this method in the point2D class and try to replace the parameter with one of type point2D, I run into compiler errors.
Thanks for your time
This sounds like the Curiously Recurring Template Pattern. Furthermore, this is completely incompatible with dynamic indirection, as the compiler cannot statically verify the dynamic type (obviously). But the CRTP can only be used to implement the function, not declare it.
template<typename T> class Point {
public:
double distTo(T other) {
/* stuff */
}
};
class Point2D : public Point<Point2D> {
// distTo automatically defined
};
Fundamentally, the interface you are trying to declare is completely impossible because you're asking the compiler to statically typecheck dynamic types. There is no solution that offers all the properties you want.
I think your requirements make no sense for a static typed language such as C++.
Think about how would you be able to use your virtual function:
point2d p1, p2;
point3d p3;
point &p = p1;
p.distTo(p2); //ok?
p.distTo(p3); //error?
That is simply not possible, because at compile time the compiler will not know if p is a reference to a point2d or a point3d, only at runtime.
You could add an explicit cast and a runtime assertion if you do it wrong, but I think that it make little sense. Simply do:
struct point { /*...*/ };
struct point2d : point {
double distTo(const point2d &other);
};
struct point3d : point {
double distTo(const point3d &other);
};
And do not call distTo using base point references.
UPDATE: If you know that your list is homogeneous, but you don't know the cardinality, then you can do:
struct point {
virtual double distTo(const point &other) =0;
};
struct point2d : point {
double distTo(const point2d &other) { /*...*/ }
virtual double distTo(const point &other) {
const point2d &other2 = static_cast<const point2d &>(other);
return distTo(other2);
}
};
struct point3d : point {
double distTo(const point3d &other) { /*...*/ }
virtual double distTo(const point &other) {
const point3d &other3 = static_cast<const point3d &>(other);
return distTo(other3);
}
};
But beware! If you call point::distTo with a wrong object, the result will be undefined!

How to compare 2 objects' private member?

I have 2 class:
class A
{
int aa;
};
class B
{
int bb;
};
class C
{
public:
bool equal(A& av,B& bv)
{
return (av.aa==bv.bb);
}
};
Of course, class C has compilation error cause of private members' access.
Is there a way to implement that equal() member of class C ?
A good solution might be to provide getters in A and B classes.
This way you keep everything encapsulated.
e.g.
class A
{
int aa;
public:
int GetAA()
{
return aa ;
}
};
This is a great scenario for using friend functions:
// forwarding references to each of the classes
class A;
class B;
class C
{
public:
bool equal(A& av,B& bv);
// notice we cannot implement equal() here,
// because A and B have not been defined yet,
// even though they have been declared.
};
class A
{
private:
int aa;
// Simply register to be a friend of A with our 'C::equal' function,
// so that we can access 'aa'
friend bool C::equal(A&, B&);
};
class B
{
private:
int bb;
// Once again, we register as a friend of C::equal,
// this time to access 'bb'
friend bool C::equal(A&, B&);
};
// finally, now that A and B have been fully defined,
// we can implement our equal method:
bool C::equal(A&av, B&bv)
{
return (av.aa == bv.bb);
}
// Sample Usage
int main()
{
A a = A();
B b = B();
C c = C();
c.equal(a, b);
}
I see questions like this and I ask why. There'a apparently no relationship between class A and class B beyond that they have an int.
The way to make this compile is to make C a friend of A and B, or at least make the equal function in C a friend of A and B (with careful use of forward declarations).
class A;
class B;
class C { static bool equal(A const &, B const &); };
class A { friend bool C::equal(A const &, B const &) };
class B { friend bool C::equal(A const &, B const &) };
bool C::equal(A& const &a, B const &b) { return a.a == b.b; }
Please note the const qualifier as it is unlikely that a comparison operator is meant to alter its input. Moreoever I have made it a static function as it doesn't use any of the members of C - it is completely unrelated. (as per your snippet).
Basically - that's how you do it. But don't do it without a LOT of thought. Just because apples and oranges both have pips, doesn't mean there's a lot of point in comparing the numbers of pips.
You can make the classes friends with each other.
But, as pointed out in comments, that's pretty horrible in most cases. The reason the member is private has to be because outside parties shouldn't access it directly.
So, either add operator==() overloads to A and B that can be used (i.e. an bool A::equal(const B&) const; method), or add accessors to return the value for external comparison.
Form friendship with two classes(c & a , c & b) and then compare.
If they are private and cannot be accessed via any kind of public interface it means conceptually they have nothing in common. so add public getAA getBB and use it to make the comparator between objects. I dislike friendship. A lot.
You could make A and B to be friend of C or add int GetVar() const methods to A and B classes.
Why do you need this?
Combine behaviour with the data.
class C
{
public:
void doSomething()
{
if(aa == bb) {
doThis();
} else
doThat();
}
}
private:
int aa;
int bb;
};
Without commenting on the relevance of the request, or alternatives for the presumed underlying reason, I believe you can compare private members thru Reflection:
FieldInfo AInfo = av.GetType().GetField("aa", BindingFlags.NonPublic | BindingFlags.Instance);
int AValue = (int) AInfo.GetValue(av);
etcetera

C++ Problem: Class Promotion using derived class

I have a class for Float32 that is derived from Float32_base
class Float32_base {
public:
// Constructors
Float32_base(float x) : value(x) {};
Float32_base(void) : value(0) {};
operator float32(void) {return value;};
Float32_base operator =(float x) {value = x; return *this;};
Float32_base operator +(float x) const { return value + x;};
protected:
float value;
}
class Float32 : public Float32_base {
public:
float Tad() {
return value + .01;
}
}
int main() {
Float32 x, y, z;
x = 1; y = 2;
// WILL NOT COMPILE!
z = (x + y).Tad();
// COMPILES OK
z = ((Float32)(x + y)).Tad();
}
The issue is that the + operator returns a Float32_base and Tad() is not in that class. But 'x' and 'y' are Float32's.
Is there a way that I can get the code in the first line to compile without having to resort to a typecast like I did on the next line?
You can use CRTP if you only need one-level deep inheritance:
template <typename T>
struct A
{
T
operator+ (const A&)
{ return T (); }
};
struct B : A <B>
{
void
lol ()
{ }
};
int
main ()
{
B a, b;
(a + b).lol ();
}
You have to override the operator+ method since your return type for operator+ is defined as Float32_base. You can do this through covariance and make the method virtual. Then override the method in your subclass (you could probably just call the method in the superclass).
You could also do this through Templates, but if you're not familiar with Templates I wouldn't suggest digging into it. Essentially you would define the virtual function the way you already did but instead of returning Float32_base, you would return your template type. (as long as your template type is a subclass then C++ should be good with contravariance). Your subclass would extend the baseclass with a template of the subclass.
You can template the FLoat32_base class on the result type of operations.
Or put everything into a single class (probably best), delegating the few platform-specific operations to platform specific functions.
Cheers & hth.,