потоковый вывод и неявная пустота * вызов функции оператора приведения

#c

#c #c

Вопрос:

код , подобный

 cin>> grade;
  

где grade — стандартный тип данных, возвращает ссылку на cin (объект istream), который разрешает каскадные входные данные….
но я читал, что если

 cin >>grade;
  

используется как условие, указанное в операторе while…функция оператора void* cast в потоке вызывается неявно…и он преобразует ссылку на объект istream в ненулевой или нулевой указатель в зависимости от успеха или неудачи последней операции ввода … и нулевой указатель преобразуется в false, а ненулевой в true…my вопросы заключаются в:

  1. что такое операторная функция void * cast и как она здесь работает
  2. как ненулевой указатель преобразуется в true, а null — в false

Комментарии:

1. Просто для того, чтобы отметить, почему это полезно: это позволяет вам выполнять цикл, подобный while(cin >> x) { /* do stuff with x */ } .

Ответ №1:

1.что такое операторная функция void * cast и как она здесь работает

Это выглядит примерно так:

 operator void* () const {
    return fail() ? 0 : this;
}
  

Вопрос в том, почему здесь не используется operator bool ? Ответ таков: потому что это допускает недопустимые преобразования, которые могут скрывать ошибки. Приведенное выше является примером идиомы safe bool.

Однако эта реализация фактически устарела. Существуют лучшие реализации этой идиомы; в статье они объясняются.

2.как ненулевой указатель преобразуется в true, а null — в false

Именно так работает C : любой ненулевой указатель считается эквивалентным true в условном выражении. Теперь, почему C вызывает operator void* здесь в первую очередь?

По сути, когда C видит объект неожиданного типа, он пытается применить одно неявное преобразование, которое сделало бы тип объекта допустимым в этом контексте. Поэтому компилятор пробует все доступные неявные преобразования и проверяет, будет ли результирующий тип приемлемым в данном контексте.

Это происходит с ней: компилятор видит while (cin >> grade) . Он знает, что это basic_istream недопустимо в контексте while условия. Таким образом, он обнаруживает, что существует operator void* , и void* является допустимым в этом контексте, поэтому C применяет это преобразование.

Комментарии:

1. @Konrad: Этого недостаточно -> return fail() ? 0 : this; ?

2. @Nawaz не был уверен, и ему было лень проверять. ?: запрещает неявное преобразование между несовместимыми типами. Возможно, 0 тип здесь правильно выведен как basic_istream* здесь. Но в любом случае приведение делает это явным.

3. @Konrad: Да. 0 совместим с любым типом указателя благодаря неявному преобразованию. Именно по этой причине его часто используют как нулевой указатель любого типа. std::istream *p = 0; , std::string *s=0; void* v = 0; все в порядке. В любом случае, 1 за хороший ответ.

4.@Nawaz Однако это разные ситуации, потому что они являются инициализациями. Инициализации также могут вызывать неявные операторы преобразования, но ?: не могут этого делать.

5. @avinash Не обязательно. Это всего лишь типичная реализация. В действительности подойдет любое значение указателя != 0, например reinterpret_cast<void*>(1) .