2017-01-20 3 views
2

У меня есть функция, которая принимает в логическое значение в качестве аргумента:Почему функция с аргументом Bool принимает строку?

void func(bool a) 
{ 
    doing something; 
} 

Но когда я звоню функции и переданной строки к нему:

func("false"); 

На самом деле он должен принимать только.

func(false); 

Он принимает строку без ошибок.

Почему?

+0

Указатель будет неявно преобразован в bool. Null pointer -> false, Non-null pointer -> true. В этом случае func получит значение * true * из ненулевой «ложной» строки в const char *. –

+0

@SingerOfTheFall Хорошо, я повторно разместил его. –

+0

есть какой-либо способ, с помощью которого я могу явно принять его для принятия boolean – waz

ответ

4

Литеральная строка - указатель на символ, а указатель будет неявно преобразован в bool.

  • Null указатель ->false
  • непустой указатель ->true

В этом случае функ получит значение true от ненулевого "лжи" строка, которая является const char* типа.

Возможно, вам понадобится функция интерпретатора для чтения «ложных», «0», «нет» и т. Д. С клавиатуры и преобразования в bool false, которые программа может понять.

+0

Правда, мы используем 'if (p) {... } ', чтобы определить, равно ли указатель равно« NULL »или нет в C/C++ все время. –

+1

Строковый литерал не является указателем. Но он неявно конвертируется в указатель, точно так же, как указатель неявно преобразуется в логическое. – user2079303

2

Указатели могут быть неявно преобразованы в bool; Значение равно false, если указатель NULL, и это true, если указатель !NULL. Следовательно, поскольку вы передаете указатель на char * -literal "false", этот указатель ! NULL и дает true. См следующего определения в cpp reference concerning of implicit conversion:

булевых конверсии

prvalue интегральной с плавающей точкой, незаданная перечисления, указатель и указатель на член типа может быть преобразованы в prvalue из тип bool. Значение 0 (для целых чисел, с плавающей запятой, и неперечисленное перечисление) и нулевой указатель и значения значений указателя на элемент становятся ложными. Все остальные значения становятся истинными

4

Согласно стандарту C++ §4.14/p1 булевых преобразования [conv.bool] (курсива моего):

A prvalue арифметики, незаданное перечисления, указатель, или указатель на тип члена может быть преобразован в prvalue типа bool. Нулевое значение, Значение нулевого указателя или значение указателя нулевого элемента преобразуется в false; любое другое значение преобразуется в значение true. Для прямой инициализации (8.6), prvalue типа std :: nullptr_t может быть преобразовано в prvalue типа bool; результирующее значение ложно.

То есть, в соответствии со стандартом C++, преобразование из строкового литерала (то есть указатель) на логическое значение является стандартным преобразованием и, таким образом, что вы испытываете совершенно нормально/стандартное поведение языка.

Вы можете ограничить функцию явным образом принимать только BOOL значения, определяя общую перегрузку вашей функции как удаленные:

template<typename T> void func(T&&) = delete; 

void func(bool a) { 
    // do something... 
} 

Live Demo

1

@ 101010 в ответ хорошо. Но в интересах тех, у кого есть старые компиляторы (которые, как я подозреваю, не согласны с этим синтаксисом), существует альтернативный подход.

Первое:
Функция шаблона декларация, без определения/реализации. Таким образом, если вы его случайно назовете func("false") или func('y') или func(0) (int), компоновщик будет жаловаться. Это заставит вас искать проблему.

template<typename T> void func(T a); // prototype only 

Объявите это наряду с вашей реальной void func(bool a) функции.

Если у вас есть это внутри класса, вы можете сделать функцию/метод шаблона конфиденциальной, что сделает ошибку в ошибке компилятора (проще понять, но если случайный неправильно введенный вызов происходит из класса или друг, он все равно будет ошибкой компоновщика).

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