#c
#c #c
Вопрос:
код , подобный
cin>> grade;
где grade — стандартный тип данных, возвращает ссылку на cin (объект istream), который разрешает каскадные входные данные….
но я читал, что если
cin >>grade;
используется как условие, указанное в операторе while…функция оператора void* cast в потоке вызывается неявно…и он преобразует ссылку на объект istream в ненулевой или нулевой указатель в зависимости от успеха или неудачи последней операции ввода … и нулевой указатель преобразуется в false, а ненулевой в true…my вопросы заключаются в:
- что такое операторная функция void * cast и как она здесь работает
- как ненулевой указатель преобразуется в 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)
.