C++,对自定义的类型用istream_iterator出错!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++,对自定义的类型用istream_iterator出错!相关的知识,希望对你有一定的参考价值。

程序如下:
#include<stdafx.h>
#include<iostream>
#include<algorithm>
#include<iterator>
#include<vector>

class Node /*自定义的类,只有两个整型成员*/

public:
int x,y;

Node()
Node(int xx,int yy):x(xx),y(yy)
/*输入输出*/
friend std::ostream& operator<<(std::ostream&,Node&);
friend std::istream& operator>>(std::istream&,Node&);
;
std::ostream& operator<<(std::ostream& out,Node& n)

out<<n.x<<','<<n.y;
return out;

std::istream& operator>>(std::istream& in,Node& n)

in>>n.x>>n.y;
return in;


int main()

std::vector<Node> vn;
/*用istream_iterator输入一批Node*/
std::copy(std::istream_iterator<Node>(std::cin),std::istream_iterator<Node>(),std::back_inserter(vn));
/*用ostream_iterator输出一批Node*/
std::copy(vn.begin(),vn.end(),std::ostream_iterator<Node>(std::cout));

return 0;

程序不长,但编译总是出错!错误信息如下:
d:\program files\microsoft visual studio\vc98\include\iterator(203) : error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'const class Node' (or there is no acceptable conversion)
d:\program files\microsoft visual studio\vc98\include\iterator(203) : while compiling class-template member function 'class std::ostream_iterator<class Node,char,struct std::char_traits<char> > &__thiscall std::ostream_iterator<class Node,ch
ar,struct std::char_traits<char> >::operator =(const class Node &)'
执行 cl.exe 时出错.

说'<<'运算符没有定义,但我明明定义了呀.
希望有解决方案的朋友能给我解释下,在这里先谢谢了!

楼上说的不错,那种更改能使编译器闭嘴
但是还有一种更改
std::ostream& operator<<(std::ostream& out, Node n)也能使编译器闭嘴
可见他的理由不是很充分,但是他的建议值得你去实行!
当一个函数中的参数在调用过程中不改变其值,就尽量用 const type& 来替换 type ,注意这里的type最好是自定义类型,因为内置类型int double用第二种更快!第一种少了赋值,直接拿来用(在不改变其内容的前提下),第二种是复制,你用vector,应该知道复制一个vector(元素比较多的情况下)的开销不小,const type& 就有利用的价值,而在内置类型的情况下,const type& 的实现过程要比一个简单的复制复杂,所以影响效率。但是很多人为了编程习惯的一致性,第二种也用 const type& (const int&...)等,其实也没什么,都可以的,影响非常小。
至于什么时候用引用 type&
恰好与上面的相反:当你想改变某个对象的值是用type &(如swap()函数(交换函数)中就最好用引用(非常量)而不是指针,cin中也是)
好了这个问题就说到这!
下来就说为什么编译器从上面的程序中扑捉到了一条错误,确切的说问题出在std::copy()上,任何algorithm中的函数都是用迭代实现的(循环,从第一个参数(起点迭代)到第二个参数(终点后迭代),其他的参数就不说了(可能还是迭代器),copy()是非改变性算法(不改变迭代所指的值)所以copy中迭代器其的类型是const_iterator(const_reverse_iterator),不能改变引用的原值。
你用常量引用(const type&)或者type作为参数类型都能够通过编译
另外,还有一种迭代器类型就是iterator(reverse_iterator)它允许改变所指元素,但是copy()无福消受,呵呵!,你用引用或指针作为参数类型就行了
很明显
std::ostream& operator<<(std::ostream&,Node&);
这里用了引用(允许改变所指的值)就违反了copy的意愿,为了让代码安全,所以指出了这个错误。
如果你只将主函数改变为:
int main ()

Node node;
cin >> node;
cout << node;

程序也没有错误,因为这里没有规定operator<<不能改变第二个参数,引用没错,但不建议!
给你说个额外的东西,你知道为什么operator<<的第一个参数和operator>>的第一个参数用的是引用(非常量)吗?因为每一次的输入(cin),输出(cout)都可能会改变输入输出流(iostream)对象(cin,cout,cerr,clog)的状态(good,eof,fail,bad),而引发异常)。
如果你输入1 2 3 Ctrl+Z(eof),也就是说你输入了一个半Node对象,这会带来什么后果呢?
输出值只有1,2,为什么呢?因为当输入第四个值(n.y)时,cin得到了eof,这使得cin的状态从good变成了eof(可以说是不好的状态),copy第二个Node没有成功,所以输出时只有1,2这一个对象。
回过头来再说你的程序,我建议你将default constructor(默认构造函数)改为
Node():x(0), y(0) {}
你那个版本起不到初始化的效果,不好的,改掉它!。
在类中能用private的就不要用public将你里边的数据成员改成private!
说的太多了,不说了,希望这能解决你的问题!
参考技术A std::ostream& operator<<(std::ostream& out,const Node& n)
输出的类型要改成 const Node &。 基本上就是尽量用const, 因为stl里面用了很多,你不用就接不到一起去

以上是关于C++,对自定义的类型用istream_iterator出错!的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2:如何对自定义复合表单类型使用约束?

在 C++ 中对自定义对象的向量进行操作 [关闭]

森说AI:AI创造营大作业--应用paddlex完成对自定义车道路的语义分割

森说AI:AI创造营大作业--应用paddlex完成对自定义车道路的语义分割

ngRepeat 对自定义指令标签

WPF - 对自定义标记扩展进行单元测试