2010-10-04 123 views
1

我对C++的了解很少,因为我只接受了几个类。我不了解使用friend函数重载输入的基本情况,输出流操作符是具有x,y实例变量的Point对象的“简单示例”。现在我在看一个真实的项目,试图了解有人写了和正在错误:重载操作符>>()

error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion) 
1>  c:\program files\microsoft visual studio 9.0\vc\include\istream(1000): could be 'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,signed char *)' [found using argument-dependent lookup] 
1>  with 
1>  [ 
1>   _Elem=char, 
1>   _Traits=std::char_traits<char> 
1>  ] 

noob问题(1),有人可以解释什么是basic_istream?错误点:

template<class _Traits> inline 
    basic_istream<char, _Traits>& __CLRCALL_OR_CDECL operator>>(
     basic_istream<char, _Traits>& _Istr, signed char *_Str) 
    { // extract a signed char NTBS 
    return (_Istr >> (char *)_Str); 
    } 

另一部分错误指向是:

void input(std::istream &in = std::cin) 
    {in >> "(" >> X >> "," >> Y >> "," >> Z >> ")" ; } 

inline friend std::istream& operator >> (std::istream& in, Coord &val) 
    {val.input(in); return in; }; 

不知道什么是错误的看着我有限的知识。它似乎是抱怨不是inline friend std :: istream & operator >>函数中的正确类型,因为basic_istream模板中存在错误(我不确定那里发生了什么)。任何建议将不胜感激。谢谢!

+0

_Never_ __undersand__使用朋友的基本情况......无论如何。 ':)' – sbi 2010-10-04 20:11:25

回答

1

首先,因为您是C++新手:不要太信任编译器错误消息。在复杂的代码(模板,重载...)中,您经常会收到与实际问题无关的消息。

在我的答案中加入评论:尽管如此,“,”和类似的对象是常量,X,Y,Z的运算符只在非const对象上声明,因此不适用。你必须复制它,或者只写一个const版本。

+0

字符串文字是常量,所以是的,“(”,“)”和“,”是常量。 – JoshD 2010-10-04 18:39:18

+0

在这种情况下,它直接与真正的问题有关:没有'operator >>'在左边接受流,在右边接受'const char [2]'。 – Cubbi 2010-10-04 18:42:13

1

我很确定你不能参数化这样的istream提取。它会很酷被证明是错误虽然:)

试试这个:

void input(std::istream &in = std::cin) 
{ 
char t; 
in >> t >> X >> t >> Y >> t >> Z >> t; 
} 
+0

但是,这并没有强制执行正确的格式。 – GManNickG 2010-10-04 18:44:10

1

不能使用的字符串作为这样的输入。你将需要使用类似

char c; 
cin.get() >> c; 
if (c != '(') throw SomeError; 
cin >> X; 
cin.get() >> c; 
if (c != ',') throw SomeError; 
cin >> Y; 

等等。

+2

你通常不希望流操作抛出。 – GManNickG 2010-10-04 18:44:34

0

basic_istream背后istream真正的类 - 的定义是这样:

namespace std { 
typedef basic_istream<char> istream; 
typedef basic_ostream<char> istream; 
typedef basic_istream<wchar_t> wistream; 
typedef basic_ostream<wchar_t> wostream; 
} 

至于为什么你在第一时间收到错误消息,问题是很显然与类似的部分:

some_istream >> "("; 

似乎想读一个字符,并有与之相匹配的是对一个左括号,以及(可能)失败,如果那不是它找到。然而,无论好坏,istream都不直接支持。要做到这一点,你可以做这样的事情:

char ch; 
some_istream >> ch; 
if (ch != '(') 
    // handle failure 

或者,你可以只读取一个字符,并承担这是什么应该在那里,不检查。这也可以允许更灵活的输入格式,所以“1 2 3”将被接受为“(1,2,3)”。对于某些情况(例如,由某人直接输入的输入),这可能相当有帮助。在其他情况下(例如来自另一程序的输入),输入信号中的任何偏差都会产生问题。

0

问题是这样的:

in >> "(" 

概念上讲,这是没有意义的。您正试图将输入读入字符串文字。 (这就像试图将输入读入常量5)。错误是因为字符串文字是字符的常量数组(因此为const char[2]类型),因此无法读入。

您可能希望这样:

void input(std::istream &in = std::cin) 
{ 
    char dummy = 0; 
    in >> dummy >> X >> dummy >> Y >> dummy >> Z >> dummy; 
} 

所有这一切都不会被读这些字符转换成一个虚拟变量。它有效,但这些角色可以是任何东西。

相反,你应该做到以下几点:

// if you do it more than once, make it a function 
bool expect_char(std::istream& in, char expected) 
{ 
    char check = 0; 
    in >> check; 

    if (check != expected) 
    { 
     in.putback(); // replace it 
     in.clear(std::ios::failbit); // set fail bit 

     return false; 
    } 
    else 
    { 
     return true; 
    } 
} 

void input(std::istream &in = std::cin) 
{ 
    if (!in) // if stream is bad, just return 
     return; 

    if (!expect_char(in, '(')) 
     return; 

    in >> X; 

    if (!expect_char(in, ',')) 
     return; 

    in >> Y; 

    if (!expect_char(in, ',')) 
     return; 

    in >> Z; 

    if (!expect_char(in, ')')) 
     return; 
} 

现在唯一的问题是,如果提取失败,中途,我们修改了点对象。理想情况下,这将是全部或没有。我们存储中间值,然后在全部工作时复制它们:

void input(std::istream &in = std::cin) 
{ 
    if (!in) 
     return; 

    if (!expect_char(in, '(')) 
     return; 

    int newX; // or whatever type it is 
    in >> newX; 

    if (!expect_char(in, ',')) 
     return; 

    int newY; 
    in >> newY; 

    if (!expect_char(in, ',')) 
     return; 

    int newZ; 
    in >> newZ; 

    if (!expect_char(in, ')')) 
     return; 

    X = newX; 
    Y = newY; 
    Z = newZ; 
} 

而且我们得到了我们之后的东西。

+0

姆姆。我确定我有一天刚刚在一个istream上发布了一个特别的角色,但现在我找不到它了。 (搜索真的很糟糕,没有全文搜索功能,除了谷歌,并且不允许数据范围。) – sbi 2010-10-04 20:46:47