2016-08-16 7 views
29

Я читаю книгу на C++, который говорит, что если я использую >> оператор возвращает объект на левой стороне оператора, так в этом примереКак std :: cin возвращает bool и сам в одно и то же время?

std::cin >> value1; 

код возвращает std::cin ,

Но если я сделаю это

while(std::cin >> value1) 

Мой код будет находиться в цикле до тех пор, пока не будет std::cin ошибка, так что должно означать, что оператор возвращает bool, что является истинным, когда std::cin не подведет и ложно, когда std::cin не работает.

Что это такое?

+18

'std :: cin' также имеет оператор преобразования в' bool', который используется в состоянии. –

+5

@ πάνταῥεῖ Комментарии для комментариев, а не ответы. – Mego

ответ

46

[...] так, что должно означать, что оператор возвращает логическое значение [...]

Не, он возвращает std::cin (по ссылке). Причина, по которой работает while(std::cin >> value);, заключается в том, что std::istream (который является типом std::cin) имеет conversion operator.

Оператор преобразования в основном допускает неявный класс (если он не помечен explicit) для преобразования в заданный тип. В этом случае std::istream определяет его operator bool, чтобы вернуть ошибку (обычно failbit);

[std::ios_base::operator bool()]

Возвращает true, если поток не имеет ошибок и готов для операций ввода/вывода. В частности, возвращается !fail().


explicit operator bool() const; 

Примечание, чем даже если оператор explicit (который не должен допускать неявные преобразования, как if (std::cin);), классификатор игнорируется, когда используется в контексте, который требует bool, как if, while петли и петли for. Это исключения, а не правила.

Вот пример:

if (std::cin >> value); //OK, a 'std::istream' can be converted into a 'bool', which 
         //therefore happens implicitly, without the need to cast it: 

if (static_cast<bool>(std::cin >> value)); //Unnecessary 

bool b = std::cin >> value; //Error!! 'operator bool' is marked explicit (see above), so 
          //we have to call it explicitly: 

bool b = static_cast<bool>(std::cin >> value); //OK, 'operator bool' is called explicitly 
+0

Это может быть менее запутанным для OP, если вы укажете, что простой 'void * ptr = NULL: if (ptr)' также работает (с которым он или она, безусловно, знакомы), потому что это _convertibility_ to 'bool', что важно , а не фактическое выражение, имеющее тип 'bool' изначально. –

+1

@LightnessRacesinOrbit Хорошая идея :) Но это может быть лучше * без * 'void *, этого следует избегать. – Rakete1111

+2

Я думаю, что в дополнение к исключениям из правила было бы полезно добавить исключение, например 'bool good = std :: cin;', которое по праву не компилируется. – Ruslan

21

std::istream (класс, который std::cin является объектом) имеет следующую функцию-член:

explicit operator bool() const; 

Это возвращает ложь, если объект находится в ошибке состояния и в противном случае. Вот почему работает конструкция while(std::cin >> value1).До C++ 11, он имел эту неоднозначность явную функцию вместо:

operator void*() const; 

который вернул пустой указатель, если объект находился в неисправном состоянии, служит той же цели.

3

Операции над потоками возвращают ссылку на поток.

Итак, не bool.

Вы можете вставить результат в if условия по той же причине, что вы можете сделать это:

void* ptr = foo(); 
if (ptr) { /*...*/ } 

И, если на то пошло, это:

int x = foo(); 
if (x) { /*...*/ } 

Оба ptr и x здесь может быть преобразован в bool для использования в состоянии. В случае std::cin преобразование достигается с помощью operator bool() в классе std::ostream, который был явно (предназначен для каламбуров) для этой точной задачи.

1

std::cin имеет тип std::istream (который является только typedef из std::basic_istream<char>)

Если вы видите different overloaded operator>> for basic_istream, все они возвращают ссылку на basic_istream. Поэтому выясняется, что operator>> здесь не возвращает bool, но вместо этого он возвращает «std::cin». Вы не увидите ни одного operator>>, возвращающего значение bool.

Итак, вопрос в том, как он преобразует std::basic_istream в bool?
Ответ: A Оператор преобразования вызывается для этой цели.

std::basic_istream наследует operator bool() от своего родительского std::basic_ios

explicit operator bool() const; 

, что делает возможным преобразовать std::basic_istream объект bool. Можно с уверенностью отметить, что он помечен explicit (см. why is it marked explicit), и все же он неявно преобразован в bool в if или while.

Ответ на этот вопрос заключается в том, что if или while используют явное преобразование «неявно». (см. this answer by @R. Martinho Fernandes). Таким образом, if, while и for являются одним из мест, где это «конверсионное преобразование» на bool происходит неявно.

 Смежные вопросы

  • Нет связанных вопросов^_^