Рассмотрим следующий код:
class Truth
{
public:
Truth(bool val) : value(val) {}
bool operator!() {std::cout<<"operator!()"<<std::endl; return !value;}
operator bool() {std::cout<<"operator bool()"<<std::endl; return value;}
private:
bool value;
};
int main()
{
Truth t(true);
if(!t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
if(!!t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
if(t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
return 0;
}
В операторах if(!t)
и if(!!t)
вызывается перегруженная реализация operator!()
, Тогда как (а не неожиданно) в выражении if(t)
вместо этого вызывается перегруженная реализация operator bool()
.
Однако, если реализация operator!()
Закомментирована, во всех 3 operator bool()
.
Я понимаю, почему это происходит, но мое беспокойство заключается в том, что перегрузка логического оператора NOT (!), Кажется, пропускает половину семантики оценки правды, в то время как оператор типа bool
-cast делает их красиво покрывать.
Я что-то упустил или должен быть обескуражен перегрузкой логического оператора NOT в пользу bool-cast-cast?
В С++ 11 вы можете просто перегрузить explicit operator bool()
. Нет причин перегружать operator!
если вы не хотите, чтобы это делало что-то другое - и если вы думаете, что хотите этого, вам, вероятно, следует подумать еще раз.
Исторически перегрузка operator bool
открывала бы дверь для неявного преобразования в любой числовой тип, что могло бы вызвать путаницу, двусмысленности и тонкие ошибки; так что лучше не делать этого. Перегрузочный operator!
был простым способом разрешить некоторые использования в условных выражениях, не открывая эту дверь, если вы не хотели увязнуть с идиомой безопасного дурака. (Ссылка предназначена только для исторического интереса, идиома устарела в С++ 11 благодаря явным операторам преобразования).
operator!
быть вызванным, еслиif (t)
не имеет!operator!
следует отговаривать Вы не сказали бы?