【问题标题】:c++ : template member addition functionc++:模板成员添加函数
【发布时间】:2014-02-27 12:18:16
【问题描述】:

我有一个接口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-&gt;valuerhs.value,因为它们不在IOperand 中。

编辑:作为 cmets 中的建议,我在 OperandIoperand 中添加了 toString 方法,我真的不知道它是否有帮助。

【问题讨论】:

  • class Operand : public Operand 应该是 class Operand : public IOperand 吗?
  • 请不要返回指针:您的运算符是内存泄漏 - 在使用模板之前先了解基础知识。
  • 我不得不这样做,这是学校的练习
  • 那你有我的同情(除非练习的重点是展示如何这样做) - 这是可怕的代码设计。
  • @JérémyPouyet 你应该在问题中添加 IOperand::toString() 方法(如主题中所定义),虽然这很可怕,但你可以用它解决你的问题(rhs.toString()应该返回 T 的字符串表示形式)

标签: c++ templates template-classes


【解决方案1】:

如果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"
}

只有当rhs 实际上是与调用operator + 相同的Operand&lt;T&gt; 的实例时,dynamic_cast 才会成功。然后在if 中进行检查。

但是,让我声明这是可怕的设计。运算符应该被重载以尽可能地表现内置的运算符(除非您以域语言样式使用它们)。在std::strings 上使用+ 也不会产生指向动态分配的std::string 的指针。

抛开代码易读性不谈,它如此错误的主要原因是它很容易泄漏内存 - 这个operator+ 的唯一合理实现将动态分配内存,并且由于它返回一个原始指针,它留给了调用者以确保内存不泄漏。 坏东西。

【讨论】:

  • @DieterLücking 也许你可以解释一下如何避免这种情况
【解决方案2】:

欢迎使用二元运算符的精彩词。当您这样做时,您希望发生什么:

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

?

基本上有两种可能的答案。你想要一个编译错误,或者你想要一个运行时错误。后者很容易通过 dynamic_cast 实现,前者很容易通过放弃你的设计,参加 CS 大学课程,然后获得博士学位,然后创建自己的二进制操作理论并发明自己的 OO 语言来实现。

当然,在做这一切的时候不要忽视像内存泄漏这样的普通事情。

【讨论】:

    【解决方案3】:

    使用类型名 T 定义 IOperandas 模板类

    class IOperand 中添加T get_value() 应该可以工作,

    重载这个函数操作数,这样就可以获取子类中定义的数据了

    【讨论】:

    • 看成IOperandT一无所知,这个答案没有什么意义......
    • Operand 已经是模板了。 IOperand 不是,并且每个 OP 都不能更改(并且将其作为模板无论如何都会破坏其目的)。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2013-09-24
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多