c ++: функция добавления члена шаблона

У меня есть интерфейс IOperand :

class IOperand
{
public:
virtual IOperand * operator+(const IOperand &rhs) const = 0;
virtual std::string const & toString() const = 0;
}

И класс Operand :

template <class T>
class Operand : public IOperand
{
public:
virtual IOperand * operator+(const IOperand &rhs) const;
virtual std::string const & toString() const;
T    value;
}

IOperand класс и функции членов operator+ а также toString прототип не может быть изменен.
Оператор-член + должен добавить 2 значения, содержащиеся в 2 IOperand, Моя проблема в том, что это значение может быть int, char или float, но я не знаю, как это сделать с помощью шаблонов. Я попробовал это:

template <typename T>
IOperand *              Operand<T>::operator+(const IOperand &rhs) const
{
Operand<T> *op = new Operand<T>;
op->value = this->value + rhs.value;
return op;
}

мой toString метод:

template <typename T>
std::string const &     Operand<T>::toString() const
{
static std::string s;  // Provisional, just to avoid a warning for the moment
std::ostringstream convert;
convert << this->value;
s = convert.str();
return s;
}

Но компилятор не находит this->value а также rhs.value потому что они не в IOperand,

РЕДАКТИРОВАТЬ: Как совет в комментариях, я добавил toString метод в Operand а также IoperandЯ не знаю, может ли это помочь.

1

Решение

Добро пожаловать в чудесное слово бинарных операторов. Что ты хочу произойдет, когда вы сделаете это:

IOperand* foo = new Operand<Matrix<Complex>>;
IOperand* bar = new Operand<Polynomial<FiniteField<5>>>;
IOperand* baz = *foo + *bar;

?

Есть в основном два возможных ответа. Вам нужна ошибка компиляции или ошибка времени выполнения. Последнее легко выполнимо с помощью dynamic_cast, первое легко выполнимо, если отбросить свой дизайн, пройти курс обучения в университете CS, затем получить степень доктора наук, затем создать собственную теорию бинарных операций и придумать собственный язык OO.

Конечно, не пренебрегайте мирскими вещами, такими как утечки памяти, делая все это.

0

Другие решения

Если IOperand действительно неприкасаемый, вам придется прибегнуть к dynamic_cast:

template <typename T>
IOperand * Operand<T>::operator+(const IOperand &rhs) const
{
if (const Operand<T> *arg = dynamic_cast<const Operand<T>*>(&rhs))
{
Operand<T> *op = new Operand<T>;
op->value = this->value + arg->value;
return op;
}
else
return NULL;  // Or any other sensible "error occured"}

dynamic_cast будет успешным, только если rhs на самом деле является примером того же Operand<T> как тот, на котором operator + называется. Затем это проверяется в if,

Тем не менее, позвольте мне заявить, что это какой ужас дизайн. Операторы должны быть перегружены, чтобы вести себя как можно более встроенными (если вы не используете их в стиле доменного языка). С помощью + на std::strings не приводит к указателю на динамически распределяемый std::string или.

Если не принимать во внимание удобочитаемость кода, то основная причина, по которой он так ошибочен, заключается в том, что очень легко утечку памяти — единственная разумная реализация этого operator+ будет выделять память динамически, и, поскольку он возвращает необработанный указатель, он остается на усмотрение вызывающей стороны, чтобы гарантировать, что память не просочилась. Плохие вещи.

3

определить класс шаблона IOperandas с именем типа T

добавлять T get_value() в class IOperand должно сработать,

перегружаем эту функцию операндом, чтобы вы могли получить данные, определенные в дочернем классе

0
По вопросам рекламы [email protected]