Я знаю, но мой наставник настаивает на том, чтобы делать это как переопределение чисто виртуального оператора, как упражнения в абстрактных классах, но я действительно не понимаю.
Ну, вы можете научитьсяо двух вещах из этого:
- Как работают виртуальные функции в целом (а пользовательский оператор - это не что иное, как обычная функция, отличается только синтаксис вызова).
- Виртуальные функции не используются.Святой Грааль не может решить что-нибудь .
Проблема в том, что классы Integer
и Real
, скорее всего, имеют различное внутреннее представление - так что вы не будетевозможность сложения / умножения / ... не зная о конкретном типе, который вы получили в качестве второго операнда.Кроме того, довольно непонятно, каким должен быть возвращаемый тип смешанных типов операндов.
Мне не нужно atm для добавления real + int, только real + real, int + 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
s, тогда у вас будет другой тип приведения.Если предположить, что Integer + Real
приведет к Real
, вам придется изменить тип возвращаемого значения на Number
, однако.
Тем не менее, есть большая проблема: возвращаемый объект уничтожается, как толькофункция оставлена, поэтому возвращаемая ссылка болтается.
Нам придется исправить это каким-то образом.Однако ссылки не подходят, поэтому мы можем выбрать интеллектуальный указатель:
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);
}
};
Эта проблема еще раз показывает, насколько неподходящим является выбранный подход на самом деле ...