如何覆盖多态性的运算符
How to override an operator for polymorphism
任何人都可以向我解释我在这里做错了什么吗?
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 <--- the ++ should be called from the Derivate class
Base* base2 = ned Derivate_2();
++base <--- the ++ should be called from the Derivate_2 class
更新:
我的问题目前的解决方案是使用 ++(*base) 我已经知道了。
但是有没有其他方法可以做到 ++base 而不是 ++(*base)?
感谢您的帮助:)
在这两行中,
X *x_base = new OK(0);
++x_base;
你创建一个指向新实例的指针,然后你递增指针,而不是指针对象。 class 层次结构的增量运算符永远不会被调用,相反,这会调用指针的内置增量运算符。您可以通过首先取消引用指针来解决此问题:
++*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;
表示您希望该值不为零。
要解决你的第二个问题,你需要为你的指针编写一个包装器 class。像
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;
};
不要这样做。
首先,使用 ++
表示 += 10
或 *= 5
可能会让你被解雇。
算术运算符适用于实际行为类似于数学对象或 pointers/iterators 的事物。从这个意义上说,任何此类对象几乎没有理由表现出任何运行时多态性。
在您让 ++
按您希望的方式在指针上工作后,您最好不要遍历 struct MU
或 struct OK
的任何数组。
运行时多态性是不得已的工具。除非你真的需要它,否则不要理会它。
最好的解决方案是摆脱虚拟和继承层次结构以及覆盖。如果做不到这一点,您应该只命名函数而不是使用运算符。
这不是个好主意。
任何人都可以向我解释我在这里做错了什么吗?
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 <--- the ++ should be called from the Derivate class
Base* base2 = ned Derivate_2();
++base <--- the ++ should be called from the Derivate_2 class
更新:
我的问题目前的解决方案是使用 ++(*base) 我已经知道了。
但是有没有其他方法可以做到 ++base 而不是 ++(*base)?
感谢您的帮助:)
在这两行中,
X *x_base = new OK(0);
++x_base;
你创建一个指向新实例的指针,然后你递增指针,而不是指针对象。 class 层次结构的增量运算符永远不会被调用,相反,这会调用指针的内置增量运算符。您可以通过首先取消引用指针来解决此问题:
++*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;
表示您希望该值不为零。
要解决你的第二个问题,你需要为你的指针编写一个包装器 class。像
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;
};
不要这样做。
首先,使用 ++
表示 += 10
或 *= 5
可能会让你被解雇。
算术运算符适用于实际行为类似于数学对象或 pointers/iterators 的事物。从这个意义上说,任何此类对象几乎没有理由表现出任何运行时多态性。
在您让 ++
按您希望的方式在指针上工作后,您最好不要遍历 struct MU
或 struct OK
的任何数组。
运行时多态性是不得已的工具。除非你真的需要它,否则不要理会它。
最好的解决方案是摆脱虚拟和继承层次结构以及覆盖。如果做不到这一点,您应该只命名函数而不是使用运算符。
这不是个好主意。