简体   繁体   中英

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 :)

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, eg

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.

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;
};

Don't do it.

First, using ++ to mean either += 10 or *= 5 should probably get you fired.

Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.

After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK .

Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.

The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.

This is not a good idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM