我有一个界面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
原型。
成员函数operator +必须添加2 IOperand
中包含的2个值。我的问题是这个值可以是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
方法,我真的不知道它是否有帮助。
答案 0 :(得分:3)
如果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::string
上使用std::string
不会导致指向动态分配的operator+
的指针。
除了代码清晰度之外,它错误的主要原因是它很容易泄漏内存 - 这个{{1}}的唯一明智的实现将动态分配内存,并且因为它返回一个原始指针,它就会被遗漏调用者确保内存不泄漏。 坏事。
答案 1 :(得分:0)
使用typename T
定义IOperandas模板类在T get_value()
中添加class IOperand
应该有效,
重载此函数操作数,因此您可以获取子类中定义的数据
答案 2 :(得分:0)
欢迎来到二元运算符的精彩词汇。当你这样做时,你想要发生什么:
IOperand* foo = new Operand<Matrix<Complex>>;
IOperand* bar = new Operand<Polynomial<FiniteField<5>>>;
IOperand* baz = *foo + *bar;
基本上有两种可能的答案。您想要编译错误,或者您想要运行时错误。后者很容易使用dynamic_cast,前者很容易通过丢弃你的设计,参加CS大学课程,然后是博士,然后创建你自己的二元操作理论和发明你自己的OO语言。
当然,不要忽视内存泄漏等平凡的事情。