重载纯虚拟运算符
Overloading pure virtual operators
我有抽象 class Number
和 4 个纯虚拟运算符(+
、-
、/
、*
)。我想制作两个派生的 classes Integer
和 Real
并在那里覆盖这些运算符。我不太了解如何声明运算符。我在网上没有找到类似我情况的例子。
我的问题是:
在抽象基础 class Number
中,我的运算符必须 return 引用 Number&
或指针 Number*
,因为我不能 return 抽象 class 本身。但是我应该传递什么作为参数呢? Number&
或 Number*
也是,但是我需要在 class 中存储数字,我应该在我的基础 class 中有类似 void* num
的东西吗?
想象一下,我有
class Number {
...
virtual Number& operator+(const Number&) = 0;
};
我应该如何在派生 class Integer
中覆盖此运算符?
I know, but my tutor insist on doing it as overriding pure virtual operator as exercising in abstract classes, but I really don't get it.
嗯,你可以从中了解到两件事:
- 虚函数的一般工作原理(自定义运算符与普通函数无异,只是调用语法不同)。
- 虚函数不是解决任何问题的圣杯。
问题是 类 Integer
和 Real
很可能具有不同的内部表示 - 因此您将无法执行 addition/multiplication/。 .. 不知道你作为第二个操作数收到的具体类型。此外,还不清楚 return 类型的混合操作数类型应该是什么。
I don't really need atm to add real+int only real+real, int+int
好吧,我们可以抓住这个:
class Number
{
public:
virtual ~Number() { } // in any case, a virtual base class should have a virtual destructor!
// fine so far:
virtual Number& operator+(Number const&) const = 0;
// we are not going to change the ^
// own instance, so we'd rather have this operator const
// (in contrast to operator+=)
};
class Integer : public Number
{
public:
Integer& operator+(Number const& other) const override
// ^ co-variant return type, so that's fine
{
// at very first, we make sure that we actually received
// an instance of type Integer
auto o = dynamic_cast<Integer const*>(&other);
if(!o)
// if not, throwing an exception is a good candidate
// for error handling...
throw std::invalid_argument("argument must be of type Integer");
// now as we know it IS an Integer:
return Integer(this->value + o->value); // or whatever...
// OOPS - the returned object gets lost when the function is left...
}
};
如果您也希望能够添加 Real
,那么您需要进行另一种类型转换。假设 Integer + Real
结果为 Real
,那么您必须将 return 类型改回 Number
。
然而,仍然存在一个很大的问题:returned 对象在函数离开后立即被销毁,因此引用 returned 是悬空的。
我们必须通过某种方式解决这个问题。但是引用不合适,所以我们可能会选择智能指针:
class Number
{
virtual std::unique_ptr<Number> operator+(Number const&) const = 0;
};
class Integer : public Number
{
std::unique_ptr<Number> operator+(Number const& other) const override
// ^
// unfortunately, now, as ordinary struct, no co-variance possible any more
{
return std::make_unique<Integer>(this->value + o->value);
}
};
这个问题再次说明实际选择的方法是多么不合适...
我有抽象 class Number
和 4 个纯虚拟运算符(+
、-
、/
、*
)。我想制作两个派生的 classes Integer
和 Real
并在那里覆盖这些运算符。我不太了解如何声明运算符。我在网上没有找到类似我情况的例子。
我的问题是:
在抽象基础 class Number
中,我的运算符必须 return 引用 Number&
或指针 Number*
,因为我不能 return 抽象 class 本身。但是我应该传递什么作为参数呢? Number&
或 Number*
也是,但是我需要在 class 中存储数字,我应该在我的基础 class 中有类似 void* num
的东西吗?
想象一下,我有
class Number {
...
virtual Number& operator+(const Number&) = 0;
};
我应该如何在派生 class Integer
中覆盖此运算符?
I know, but my tutor insist on doing it as overriding pure virtual operator as exercising in abstract classes, but I really don't get it.
嗯,你可以从中了解到两件事:
- 虚函数的一般工作原理(自定义运算符与普通函数无异,只是调用语法不同)。
- 虚函数不是解决任何问题的圣杯。
问题是 类 Integer
和 Real
很可能具有不同的内部表示 - 因此您将无法执行 addition/multiplication/。 .. 不知道你作为第二个操作数收到的具体类型。此外,还不清楚 return 类型的混合操作数类型应该是什么。
I don't really need atm to add real+int only real+real, int+int
好吧,我们可以抓住这个:
class Number
{
public:
virtual ~Number() { } // in any case, a virtual base class should have a virtual destructor!
// fine so far:
virtual Number& operator+(Number const&) const = 0;
// we are not going to change the ^
// own instance, so we'd rather have this operator const
// (in contrast to operator+=)
};
class Integer : public Number
{
public:
Integer& operator+(Number const& other) const override
// ^ co-variant return type, so that's fine
{
// at very first, we make sure that we actually received
// an instance of type Integer
auto o = dynamic_cast<Integer const*>(&other);
if(!o)
// if not, throwing an exception is a good candidate
// for error handling...
throw std::invalid_argument("argument must be of type Integer");
// now as we know it IS an Integer:
return Integer(this->value + o->value); // or whatever...
// OOPS - the returned object gets lost when the function is left...
}
};
如果您也希望能够添加 Real
,那么您需要进行另一种类型转换。假设 Integer + Real
结果为 Real
,那么您必须将 return 类型改回 Number
。
然而,仍然存在一个很大的问题:returned 对象在函数离开后立即被销毁,因此引用 returned 是悬空的。
我们必须通过某种方式解决这个问题。但是引用不合适,所以我们可能会选择智能指针:
class Number
{
virtual std::unique_ptr<Number> operator+(Number const&) const = 0;
};
class Integer : public Number
{
std::unique_ptr<Number> operator+(Number const& other) const override
// ^
// unfortunately, now, as ordinary struct, no co-variance possible any more
{
return std::make_unique<Integer>(this->value + o->value);
}
};
这个问题再次说明实际选择的方法是多么不合适...