【问题标题】:How to override an operator for polymorphism如何为多态性覆盖运算符
【发布时间】:2019-07-11 18:17:29
【问题描述】:

谁能向我解释我在这里做错了什么?

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


Base* base2 = ned Derivate_2();

++base


更新:

我的问题的当前解决方案是使用我已经知道的 ++(*base)

但是有没有其他方法可以用 ++base 代替 ++(*base)


感谢您的帮助:)

【问题讨论】:

  • x_base 是指向X 的指针。递增指针与将递增运算符应用于对象不同。您的代码打印 x_base-&gt;x 具有未定义的行为,因为在递增之后,x_base 不会指向存在的对象。将增量更改为++(*x_base)
  • 对于您更新的问题,答案是否定的。您不能覆盖指向 Base 的原始指针的内置运算符。
  • 那是真的,但是您可以将指针包装在另一个类中并为该包装类编写重载。

标签: c++ polymorphism operator-overloading operators


【解决方案1】:

在这两行中,

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 &lt;&lt; x_base-&gt;x; 表明您希望该值不为零。

【讨论】:

  • 在这种情况下,是否有任何解决方案可以得到相同的结果,而不是写 ++(*x) 来写 ++x?或者这完全不可能。
  • @Vali 我认为这个答案表明您可以通过使变量 x 具有类型 X&amp; 而不是 X* 来解决您的问题。然后++x 将作用于对象而不是指针。坦率地说,我认为这比其他答案更好。
【解决方案2】:

要解决您的第二个问题,您需要为指针类编写一个包装器。类似的东西

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

【讨论】:

  • 这会产生非常令人不快的效果,除非您将++ 应用于它,否则它会产生像指针一样的行为。在我看来,这违反了最小意外原则。
【解决方案3】:

别这样。

首先,使用++ 表示+= 10*= 5 可能会让你被解雇。

算术运算符用于实际行为类似于数学对象或指针/迭代器的事物。从这个意义上说,任何此类对象几乎没有理由表现出任何运行时多态性。

在您让++ 在指针上按您希望的方式工作后,您最好不要遍历struct MUstruct OK 的任何数组。

运行时多态性是不得已而为之的工具。除非你真的需要它,否则不要打扰它。

最好的解决方案是摆脱虚拟和继承层次结构和覆盖。如果做不到这一点,你应该只命名函数而不是使用运算符。

这不是一个好主意。

【讨论】:

    猜你喜欢
    • 2014-01-05
    • 2011-04-12
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2012-07-09
    相关资源
    最近更新 更多