Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override an operator for polymorphism

Can anyone explain to me what I'm doing wrong here?

struct X {
    int x{};

    explicit X(int x) : x(x) {}

    virtual X &operator++() = 0;
};

struct OK : X {
    int ok{};

    explicit OK(int ok) : X(ok), ok(ok) {}

    X &operator++() override {
        ok += 10;
        return *this;
    }
};

struct MU : X {
    int mu{};

    explicit MU(int mu) : X(mu), mu(mu) {}

    X &operator++() override {
        mu *= 5;
        return *this;
    }
};

int main() {
    X *x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
};

All that I'm trying to do is to use the idea of polymorphism for operators, in special the operator++. I want to have a result something like this:


Base* base = new Derivate();

++base <--- the ++ should be called from the Derivate class


Base* base2 = ned Derivate_2();

++base <--- the ++ should be called from the Derivate_2 class


UPDATE:

The current solution to my problem is to use ++(*base) which I know about this already.

But is there any other way to do ++base instead of ++(*base)?


Thanks for the help :)

like image 681
Vali Avatar asked Feb 18 '19 11:02

Vali


People also ask

How is polymorphism invoked in operator overload?

You invoke the overloaded functions by matching the number and type of arguments. The information is present during compile-time. This means the C++ compiler will select the right function at compile time. Compile-time polymorphism is achieved through function overloading and operator overloading.

Can operators be overridden?

You can override operators, but they might not do what you want. The reason is that operators (actually overloads in general) are selected from the static type of an object. If you now have a reference-to-base which is bound to a derived instance, it will not call the operator for the derived class.

Can we override operator in C++?

You can redefine or overload the function of most built-in operators in C++. These operators can be overloaded globally or on a class-by-class basis. Overloaded operators are implemented as functions and can be member functions or global functions.

Can you override operators in Java?

Java doesn't supports operator overloading because it's just a choice made by its creators who wanted to keep the language more simple. Every operator has a good meaning with its arithmetic operation it performs. Operator overloading allows you to do something extra than what for it is expected for.


2 Answers

To solve your second question you need to write a wrapper for your pointer class. Something like

class XPtr
{
public:
    XPtr(X* p) : ptr(p) {}
    X* operator->() { return ptr; }
    X& operator*() { return *ptr; }
    XPtr& operator++() { ++*ptr; return *this; }
private:
    X* ptr;
};

int main() {
    XPtr x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
};
like image 29
john Avatar answered Sep 22 '22 03:09

john


In these two lines,

X *x_base = new OK(0);
++x_base;

you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:

++*x_base; // or ++(*x_base), might be more readable

You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.

OK ok(0);
X& x_base = ok;

++x_base; // now, x_base is a reference, no need to dereference it

Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.

like image 193
lubgr Avatar answered Sep 21 '22 03:09

lubgr