【问题标题】:Why operator = doesn't get inherited from a template class为什么 operator = 没有从模板类继承
【发布时间】:2011-05-06 13:14:59
【问题描述】:

我有以下模板代码:

class ClassName{};

template <class T>
class TemplatePtr
{
public:
    void operator=(T* p)
    {

    }
};

class TemplatePtr_ClassName: public TemplateePtr<ClassName>
{
public:
    ~TempaltePtr_ClassName();
};


void Test()
{
    TemplatePtr_ClassName data;
    data = new ClassName;
}

但编译失败并显示错误消息(VS2008):

错误 C2679: 二进制 '=' : 未找到采用 >>'ClassName *' 类型的右侧操作数的运算符(或没有可接受的转换)

为什么我在模板基类中定义了一个运算符,它不起作用?

【问题讨论】:

  • 我不敢问你为什么要超载。
  • @Roger Pate 看到那个析构函数了吗?我想自己做一些清理工作,基础模板类中没有提供,不同的类可能会有所不同
  • @lz_prgmr:我理解继承(虽然你应该看特征类),但不是 TemplatePtr 中的重载。
  • @Roger Pate 实际上,这是从一个大型模板类中提取的,以便更清楚地显示问题。该模板类被设计为像 SmartPtr 一样使用,但我发现我需要做一些清理工作,所以我继承了它。
  • @Roger Pate 特征类是个好主意,但我可能无权更改 TemplatePtr 的实现(或者不想通过更改非常低级别的、广泛的-接近发布时使用的类)

标签: c++ templates inheritance


【解决方案1】:

operator = 始终被派生类实现隐藏,除非提供了明确的 using 声明。对于类模板和普通类都是如此。

顺便说一句,您对 operator= 的声明非常不标准。它通常是为“A”类声明的。

A& operator=(A const &);

这可能是您正在寻找(和编译)的东西

template <class T> 
class TemplatePtr 
{ 
public: 
    TemplatePtr& operator=(TemplatePtr const &) 
    {return *this;} 
}; 

template<class T>
class TemplatePtr_ClassName: public TemplatePtr<T> 
{ 
public:
   ~TemplatePtr_ClassName(){};
   TemplatePtr_ClassName& operator=(TemplatePtr_ClassName const &that){
      TemplatePtr<T>::operator=(that);        // invoke base class assignment operator
      return *this;
   }
}; 


int main() 
{ 
    TemplatePtr_ClassName<int> data; 
    data = *new TemplatePtr_ClassName<int>; 
    // delete stuff
} 

【讨论】:

  • 答案中提到的using 声明的代码将是:using TemplatePtr&lt;T&gt;::operator=;TemplatePtr_ClassName 类中的类花括号内。 using 声明的缺点是它还会将TemplatePtr&lt;T&gt;::operator=( TemplatePtr&lt;T&gt; const &amp; )(基类型中隐式定义的赋值运算符)带入作用域,因此您不仅可以将T* 分配给派生类,还可以TemplatePtr&lt;T&gt; const &amp;.
  • 是的,这就是我展示了使用派生类中的基类赋值运算符(而不是使用'using'指令)的工作代码的原因
  • @Chubsdad 我的意图是能够从 T* 进行分配,并且我想编写自己的析构函数来专门进行清理。所以你的方式可能不适合这个目的。
  • @lz_prgmr:您也可以为 T* 重载 operator=。 TemplatePtr_ClassName& operator=(T const *that);
  • @Chubsdad 你的类设计启发了我提供一个常用的模板类来为某些类型清理其析构函数中的东西,而无需更改其基本模板类。我认为这是我目前情况的最佳选择。
【解决方案2】:

它被继承了。但是,TempaltePtr_ClassName 的编译器生成的赋值运算符隐藏了继承的运算符。您可以通过添加使其可见

using TempaltePtr<ClassName>::operator=;

到你的派生类。

【讨论】:

  • 这也有将TemplatePtr&lt;T&gt;::operator=( Template&lt;T&gt; const &amp; ) 带入范围的缺点,这可能是不想要的。
  • @Iz_prgmr 是的。这在非默认构造函数的情况下最为明显。例如,如果您有一个 TempaltePtr::TempaltePtr(T* p) 构造函数,则必须将 TempaltePtr_ClassName::TempaltePtr_ClassName(ClassName* p) : TempaltePtr&lt;Classname&gt;(p) {} 添加到您的类中。
  • @lz_prgmr,好吧,构造函数和析构函数没有名称,因此无法隐藏。唯一的其他特殊成员函数是 operator=。运算符 & 不是一个特殊的成员函数——编译器不会生成一个。
  • @Sjoerd,这不是因为隐藏。您不能使用using 取消隐藏“继承的构造函数”。
  • @lz_prgmr,是的,默认构造函数、复制构造函数、析构函数和复制赋值运算符是唯一的特殊成员函数(这是标准所指的术语) .
猜你喜欢
  • 2012-11-22
  • 2022-12-12
  • 2018-05-23
  • 2018-01-18
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多