取消引用运算符不起作用(语法问题?)
Dereference operator doesn't work (syntax issue?)
所以我有一个非常简单的单链表实现示例。我有一个 begin
函数作为 forward_list
的 public 成员,return 是指向列表第一个(根)元素的指针。
现在因为它 return 是指向包含各种成员的 _node
对象的指针,据我所知,必须提供取消引用运算符重载才能 _node
知道取消引用时 return 的内容。
在取消引用运算符定义中,我尝试 returning _node
的 value
,这看起来很合乎逻辑,因为 begin
return 是一个_node
这意味着取消引用 begin
会给我 _node
后面的 value
。显然不是,正如 MSVC 编译器告诉我的那样:binary '<<': no operator found which takes a right-hand operand of type '_node<TType>' (or there is no acceptable conversion)
#include <iostream>
#include <cstddef>
//forward declarations
template<class TType> class forward_list;
template<class TType>
class _node
{
private:
TType key;
_node *next;
friend class forward_list<TType>;
public:
TType operator*() { return this->key; } //problem is here
};
template<class TType>
class forward_list
{
private:
_node<TType> *_root;
_node<TType> *_tail;
std::size_t _size;
private:
void _add_node_front(const TType &new_key)
{
_node<TType> *new_node = new _node<TType>{ new_key, this->_root };
if (this->_root == nullptr)
this->_tail = new_node;
this->_root = new_node;
++this->_size;
}
public:
forward_list() : _root(nullptr), _tail(nullptr), _size(0) {}
void push_front(const TType &new_key) { this->_add_node_front(new_key); }
_node<TType> *begin() { return this->_root; }
};
int main()
{
forward_list<int> l;
l.push_front(23);
l.push_front(57);
l.push_front(26); //26 57 23
std::cout << *l.begin(); //expected to print out "26"
}
EDIT:: 感谢 Joachim Pileborg 的建议。具有以下变化的魅力:
_node<TType> begin() { return *this->_root; }
您正在返回一个指针:
_node<TType> *begin();
所以你需要取消引用两次:
- 取消引用指针
- 调用您的运算符(它是为
_node<...>
定义的,而不是为 _node<...> *
定义的,它不会被调用而不是简单的取消引用)
也许,更好的方法是替换
TType operator*();
使用用户定义的转换,这将 return this->key;
:
operator TType& ();
operator TType const& () const;
而且您不需要第二次取消引用。
问题是您取消引用了 指针 ,它为您提供了一个类型为 _node<int>
的对象,然后您可以再次对它使用取消引用运算符。
所以您可以使用两个取消引用运算符来解决您的问题:
**i.begin()
另一种解决方案是 return 节点 按值 而不是 return 指向它的指针,这就是迭代器在标准中的工作方式容器。
问题出在这一行:
std::cout << *l.begin(); //expected to print out "26"
您尚未定义 operator<< 以将这些对象之一流式传输到 ostream。
您出错的直接原因是 begin
return 是一个 _node*
,而您的超载 operator*
需要一个 _node
。
如果你想实现一个符合标准的容器,你的begin
操作符应该return一个迭代器(按值),而不是一个(指针到 a) 节点。这个迭代器应该实现 operator*
(还有 operator++
和一堆其他东西)。节点 class 不适合作为迭代器。您需要一个单独的 class。 Google 类似于 "implementing my own iterators".
如果您实现迭代器,请不要向最终用户公开您的节点 class。
如果您只需要任何不符合任何特定条件的列表,最好不要重载任何运算符。使用 getValue
或其他东西。
所以我有一个非常简单的单链表实现示例。我有一个 begin
函数作为 forward_list
的 public 成员,return 是指向列表第一个(根)元素的指针。
现在因为它 return 是指向包含各种成员的 _node
对象的指针,据我所知,必须提供取消引用运算符重载才能 _node
知道取消引用时 return 的内容。
在取消引用运算符定义中,我尝试 returning _node
的 value
,这看起来很合乎逻辑,因为 begin
return 是一个_node
这意味着取消引用 begin
会给我 _node
后面的 value
。显然不是,正如 MSVC 编译器告诉我的那样:binary '<<': no operator found which takes a right-hand operand of type '_node<TType>' (or there is no acceptable conversion)
#include <iostream>
#include <cstddef>
//forward declarations
template<class TType> class forward_list;
template<class TType>
class _node
{
private:
TType key;
_node *next;
friend class forward_list<TType>;
public:
TType operator*() { return this->key; } //problem is here
};
template<class TType>
class forward_list
{
private:
_node<TType> *_root;
_node<TType> *_tail;
std::size_t _size;
private:
void _add_node_front(const TType &new_key)
{
_node<TType> *new_node = new _node<TType>{ new_key, this->_root };
if (this->_root == nullptr)
this->_tail = new_node;
this->_root = new_node;
++this->_size;
}
public:
forward_list() : _root(nullptr), _tail(nullptr), _size(0) {}
void push_front(const TType &new_key) { this->_add_node_front(new_key); }
_node<TType> *begin() { return this->_root; }
};
int main()
{
forward_list<int> l;
l.push_front(23);
l.push_front(57);
l.push_front(26); //26 57 23
std::cout << *l.begin(); //expected to print out "26"
}
EDIT:: 感谢 Joachim Pileborg 的建议。具有以下变化的魅力:
_node<TType> begin() { return *this->_root; }
您正在返回一个指针:
_node<TType> *begin();
所以你需要取消引用两次:
- 取消引用指针
- 调用您的运算符(它是为
_node<...>
定义的,而不是为_node<...> *
定义的,它不会被调用而不是简单的取消引用)
也许,更好的方法是替换
TType operator*();
使用用户定义的转换,这将 return this->key;
:
operator TType& ();
operator TType const& () const;
而且您不需要第二次取消引用。
问题是您取消引用了 指针 ,它为您提供了一个类型为 _node<int>
的对象,然后您可以再次对它使用取消引用运算符。
所以您可以使用两个取消引用运算符来解决您的问题:
**i.begin()
另一种解决方案是 return 节点 按值 而不是 return 指向它的指针,这就是迭代器在标准中的工作方式容器。
问题出在这一行:
std::cout << *l.begin(); //expected to print out "26"
您尚未定义 operator<< 以将这些对象之一流式传输到 ostream。
您出错的直接原因是 begin
return 是一个 _node*
,而您的超载 operator*
需要一个 _node
。
如果你想实现一个符合标准的容器,你的begin
操作符应该return一个迭代器(按值),而不是一个(指针到 a) 节点。这个迭代器应该实现 operator*
(还有 operator++
和一堆其他东西)。节点 class 不适合作为迭代器。您需要一个单独的 class。 Google 类似于 "implementing my own iterators".
如果您实现迭代器,请不要向最终用户公开您的节点 class。
如果您只需要任何不符合任何特定条件的列表,最好不要重载任何运算符。使用 getValue
或其他东西。