我正在研究一个包含私有嵌套节点类的链表类。我想通过使用重载的加法运算符在我的列表中向前推进n个节点,但clang给了我错误"重载'运算符+'必须是一元或二元运算符(有3个参数)"。我认为当您将隐含的this形参声明为友元函数时,它就消失了。
首先是头文件
template <class T>
class List
{
private:
class ListNode
{
public:
ListNode();
ListNode(const T& ndata);
friend ListNode* operator+(const ListNode* &node, int n);
ListNode* next;
ListNode* prev;
};
public:
friend ListNode* operator+(const ListNode* &node, int n);
,我的实现如下:
template <class T>
typename List<T>::ListNode* List<T>::ListNode::operator+(const ListNode* &node, int n)
{
ListNode* current = node;
while (n--){
if (current->next != 0)
current = current->next;
}
return current;
}
从根本上说,你试图做的事情的问题是它在指针上重载操作符。这是有问题的。尽可能简化您的代码,以下代码不会生成:
class foo{};
foo *operator+(foo *, int) {
return nullptr;
}
int main() {}
尝试给出:
$ g++ gl.cpp
gl.cpp:5:26: error: ‘foo* operator+(foo*, int)’ must have an argument of class or enumerated type
foo *operator+(foo *, int) {
如果您确实想使用operator+
,最简单的方法可能是使用成员操作符形式:
template<class T>
class List {
class ListNode { ...
public:
ListNode &operator+(int n) {
ListNode *current = this;
while (n--)
if (current->next != 0)
current = current->next;
return *current;
}
};
...
};
然而,这有点误导,因为您实际上并没有向节点添加整数,而是获得下一个节点。next
方法可能更清楚:
template<class T>
class List {
class ListNode { ...
public:
ListNode *next(int n) {
ListNode *current = this;
while (n--)
if (current->next != 0)
current = current->next;
return current;
}
};
...
};
如前所述,指针上的操作符重载是有问题的,同样,最简单的方法是将operator+
设置为成员函数。但是,有一种方法可以获得您想要的行为…
技巧是将指针包装在一个类似指针的对象中(通常称为迭代器)。
一个演示的工作示例:
class List {
struct Node {
Node* next; int data;
};
Node* m_head{0};
public:
// the fake pointer type.
struct Iter {
Iter(Node* initial = 0)
: m_base(initial) {}
Node* operator->()
{ return m_base; }
bool operator!=(const Iter& other) const
{ return m_base != other.m_base; }
private:
Node* m_base;
};
// get head as fake pointer.
Iter head()
{ return m_head; }
void push_front(const int&);
};
void List::push_front(const int& x)
{
Node* n = new Node;
n->data = x;
n->next = m_head; m_head = n;
}
// non-member operator.
List::Iter operator+(List::Iter i, int count)
{
for ( ; count > 0 && i != 0; count-- )
i = i->next;
return i;
}
int main(int argc, char* argv[])
{
List list;
for ( int i = 0; i < 10; i++ )
list.push_front(i);
for ( auto i = list.head(); i != 0; i = i+1 )
std::cout << i->data << ' ';
std::cout << std::endl;
return 0;
}