【问题标题】:Template operator returning a reference to an abstract class返回对抽象类的引用的模板运算符
【发布时间】:2015-04-06 21:11:32
【问题描述】:

伙计们,为什么这段代码不起作用?

template <typename t>
class Abstract
{
public:
   ~Abstract(){}
   virtual Abstract<t>& operator +(Abstract<t>&) = 0;
};

template <typename t>
class Not_Abstract : public Abstract
{
t* tab; //let Not_Abstract store an array of objects of type t, whatever
public:
  ~Not_Abstract(){ delete[] tab; }
  Not_Abstract<t>& operator +(Not_Abstact<t>&);
};

虽然我不知道,既然引用是一个指针,那么两个运算符的定义是等价的;但它们似乎是独立的功能。有什么办法可以在“抽象”中保留虚拟运算符并仍然使代码正常运行?

【问题讨论】:

  • 编译器应该给出一个明确的错误。编辑:Clang 在 Not_Abstract 声明行给出 error: expected class name。这不是很清楚,但Abstract 是一个模板,而不是一个类。除此之外,一个简单的错字是一个明显的错误,否则它会编译。不确定您遇到了什么问题。
  • 我们不是 Fellas 我们是 coders。完全不同。 :)
  • @chris 您可能需要明确说明:它们应该继承自 Abstract&lt;t&gt;
  • 减 1:请发布实际演示您遇到的问题的代码。上面的代码无法在完全不同的行上编译。如果你解决了这个问题,请告诉我,我会反转负 1。

标签: c++ templates operators abstract-class


【解决方案1】:

两个运算符的定义是等价的

不,他们不是。一个有Abstract&amp; 参数,另一个有Not_Abstract&amp; 参数。要覆盖,参数类型必须匹配,以便覆盖的调用方式与其覆盖的函数相同。

有什么办法可以在“抽象”中保留虚拟运算符并仍然使代码正常运行?

覆盖必须采用Abstract&amp;,并且无论是否使用Non_Abstract 调用,都必须做正确的事情。

【讨论】:

  • 所以,结果必须匹配,而不是参数?如果我将参数更改为对我的抽象类的引用,我将无法访问它的私有部分,因为它没有。
  • 等等,还是反过来? xD
  • @Jules:结果可以是协变的——也就是说,覆盖可以返回一个更派生的类型——这很好。参数必须匹配——虚函数必须可以通过基类调用,因此必须可以使用从Abstract 派生的任何类型调用,而不仅仅是Not_Abstract。您将需要更多的虚拟函数(可能类似于访问者模式)或dynamic_cast,将参数视为Non_Abstract
【解决方案2】:

要使派生类中的函数成为基类中虚成员函数的实现,必须声明它以使参数类型保持不变:

Not_Abstract<t>& operator +(Abstact<t>&);

如果您想确保将Non_Abstract 的实例作为运算符的RHS 处理,则必须在函数的实现中执行dynamic_cast

template <typename t>
Not_Abstract<t>& Not_Abstract<T>::operator +(Abstact<t>& rhsBase)
{
   Not_Abstract<t>& rhs = dynamic_cast<Not_Abstract<t>&>(rhsBase);
   // ... Now work with a Not_Abstract object
   // ....

}

如果rhsBase 不能转换为Not_Abstract&lt;t&gt;&amp;dynamic_cast 将抛出std::bad_cast 异常。您的代码必须准备好处理抛出的异常。

【讨论】:

    猜你喜欢
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2011-01-13
    相关资源
    最近更新 更多