Как переопределить оператор для полиморфизма - PullRequest
0 голосов
/ 18 февраля 2019

Может кто-нибудь объяснить мне, что я здесь делаю не так?

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

Все, что я пытаюсь сделать, это использовать идею полиморфизма для операторов, в частности оператора ++.Я хочу, чтобы результат был примерно таким:


Base * base = new Derivate ();

++ base <--- должен вызываться ++из класса Derivate </p>


Base * base2 = ned Derivate_2 ();

++ base <--- ++ должен вызываться из Derivate_2класс </p>


ОБНОВЛЕНИЕ:

Текущее решение моей проблемы - использовать ++ (* base) , который язнать об этом уже.

Но есть ли другой способ сделать ++ base вместо ++ (* base) ?


Спасибо запомощь:)

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

Чтобы решить ваш второй вопрос, вам нужно написать оболочку для вашего класса указателя.Что-то вроде

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;
};
0 голосов
/ 21 февраля 2019

Не делайте этого.

Во-первых, использование ++ означает, что либо += 10, либо *= 5, вероятно, вас уволят.

Арифметические операторы предназначены для вещей, которые на самом делевести себя как математические объекты или указатели / итераторы.В этом смысле почти нет причин для какого-либо такого объекта демонстрировать какой-либо полиморфизм во время выполнения.

После того, как вы заставите ++ работать с указателем, как вы хотите, вам лучше никогда не выполнять итерацию по каким-либо массивам struct MU или struct OK.

Динамический полиморфизм - это средство последней инстанции.Не беспокойтесь, если вам это действительно не нужно.

Лучшее решение - избавиться от виртуальной и иерархии наследования и переопределения.В противном случае вы должны просто назвать функции вместо использования операторов.

Это не очень хорошая идея.

0 голосов
/ 18 февраля 2019

В этих двух строках

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

вы создаете указатель на новый экземпляр, а затем увеличиваете указатель, а не указатель.Оператор приращения вашей иерархии классов никогда не вызывается, вместо этого это вызывает встроенный оператор приращения для указателей.Это можно исправить, предварительно разыменовав указатель:

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

Вы также можете работать со ссылками вместо указателей, что позволяет использовать синтаксис приращения без необходимости разыменования указателя, например

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

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

Обратите внимание, что реализация вызываемой перегрузки оператора не меняет значение X::x.std::cout << x_base->x; после увеличения означает, что вы ожидаете, что значение будет ненулевым.

...