【问题标题】:Overloading operator++ in a templated class在模板类中重载 operator++
【发布时间】:2012-09-17 06:32:10
【问题描述】:

我一直在摸索这个问题,在筛选了所有其他帖子之后,我想我已经不知所措了。

我决定要在 C++ 中练习一些模板编码和运算符重载,因此我认为快速而肮脏的 LinkList 实现会走得很远。我快速破解了一个节点和列表类集,如下:

template <class T>
class Node{
public:
  Node* getNext(){ return Next; }

private:
  Node* Next;
  T data;
};

template <class T>
class List{
public:
  List& operator++();

private:
  Node<T>* nptr;
};

template <class T>
List<T>& List<T>::operator++(){
  if( nptr->getNext() ){
    nptr = nptr->getNext();
  }
  return *this;
}

main call:
int main(){
  List<int>* listObj = new listObj<int>();
  ...push on some nodes with random values...
  ++listObj;
  KABOOM
}

为了便于阅读,我保持代码简短。假设我在创建节点时总是将 Next 初始化为 NULL,有一个 push 函数可以将更多节点添加到末尾,这也将最后一个节点的“Next”变量设置为该新节点,并且 nptr 也开始初始化为 NULL .我已经测试了所有“假定的”功能(构造、初始化、推送节点),我什至可以将 operator++ 函数打包为一个增量函数......

void Increment(){
  if( nptr->getNext() ){
    nptr = nptr->getNext();
  }
}

call:
listObj->Increment();

...而且效果很好。换句话说:编译器没有将我的 ++foo 版本分配给代码中的任何用途!我什至可以用调试器证明这一点,观察它增加 List 对象的地址,而不是像我想要的那样更新 nptr。

现在,我看到了一个将here 加为好友的建议,我尝试了一下:

friend List& operator++(){
  if( nptr->getNext() ){
    nptr = nptr->getNext();
  }
  return *this;
}

但是当我这样做时,我得到一个编译错误:

List& operator++() must have an argument of class or enumerated type

我是一个头脑冷静的程序员,我认为它希望我找出传入的 RHS,这自然也不起作用。我放弃写出那条断断续续的推理路径,因为我相当确信这不是正确的方向。

所以考虑到编译器似乎对我的代码很满意(或者至少不会因为它实际上没有在任何地方分配它而感到不安),为什么它仍然抓取非模板版本运算符并将其视为 int?我将如何纠正代码以使编译器改为使用提供的函数?

提前致谢!

【问题讨论】:

  • 我不确定这是否能解释您的问题,但您在类外定义 operator++ 函数的方式不正确。需要在前面加上template &lt;typename T&gt;,然后定义为List&lt;T&gt;&amp; List&lt;T&gt;::operator++()
  • 你不显示它,但你初始化nptr成员?不是吗?
  • 致两个 cmets:我在写出来时出现了部分错误(谢谢,已修复),是的,我这样做了(在我开始将节点推入列表之前设为 NULL)。
  • 你试图定义链表的整个方式是完全不安全的内存泄漏。您可以在垃圾收集语言中这样做,但在 C++ 中,这仅适用于智能指针。更惯用的方式(std::list 也是这样做的)是将整个列表作为一个单元进行 RAII。 — 无论哪种方式,您都不想拥有List&lt;T&gt;::operator++。 “递增”的不是列表,而是 您正在查看的列表中的位置,因此您需要类似 List&lt;T&gt;::iterator::operator++ 的内容。

标签: c++ templates operator-overloading


【解决方案1】:

用户定义的运算符从不适用于指针等内置类型。如果有的话,您需要在使用增量运算符之前取消引用指向您的 List 的指针:

++*listObj;

如果没有*,则使用内置的增量运算符,这显然不是您想要的。我假设您的 KABOOM 实际上取消了您的指针的引用:您通常希望显示出问题的确切代码,并且您希望更准确地了解实际出了什么问题。我还假设您创建的是实际编译代码,而不是您引用的代码......

【讨论】:

  • 虽然问题确实经常出现在未引用的代码中,但在这种情况下,很明显它就像这样简单:在指针上使用运算符而不是对象。
  • 是的,是的,是的。这是一个精简的 sn-p,缺少实际上用数据填充测试用例的大多数有用功能。 KABOOM 是我说“这里出现段错误”的奇怪方式,事实证明,这是对节点中数据的访问请求。另外,在取消引用时捂脸,谢谢!
猜你喜欢
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多