2015-03-04 2 views
5

Я объявил объявление функции C++ с тремя аргументами, два из которых имели значения по умолчанию.Компилятор C++ не предупреждает о недостающем аргументе до конца аргументов по умолчанию

void func(int const n, bool const flag=true, int *array=NULL) { 
    /* print contents of array */ 
} 

Когда я вызове функции ошибочно, опуская второй аргумент, но в том числе и третий аргумент, как так

int array[5]={1,2,3,4,5}; 
func(5,array); 

ни GCC, ни Intel компиляторов (те, по умолчанию на Ubuntu 14.04 LTS) жаловались, что последний аргумент был указан без указания второй последней. Код запущен, но отправлен в NULL для массива (я ожидал, что код завершится с ошибкой).

Мой вопрос, почему не составителям жалуются, что не может найти функцию согласования с момента подписания моего вызова должен был появиться в

funct(int const, int *) 

Какие варианты можно включить во время компиляции, чтобы вызвать предупреждение об этом ошибочном использовании?

+0

Вы должны включить «крик оценщика кода на вас для добавления аргументов по умолчанию» warning :) – CoryKramer

+0

Нет никакого предупреждения, о котором я знаю. Array-> pointer-> bool - отлично определенная последовательность преобразований. – chris

+0

Это очень упрощенный, но репрезентативный пример, построенный из гораздо более сложного кода, где, если бы я избегал аргументов со значениями по умолчанию, у меня было бы так много перегруженных функций для всех вариантов, которые были бы довольно громоздкими. – raovgarimella

ответ

14

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

Update

От C++ 11 Стандарт на:

4 Standard conversions [conv]

1 Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions. A standard conversion sequence is a sequence of standard conversions in the following order:

— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.

— Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.

— Zero or one qualification conversion.

[ Note: A standard conversion sequence can be empty, i.e., it can consist of no conversions. —end note ]

A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.

+0

Вот почему аргументы по умолчанию настолько ужасающие. – maxywb

+0

Есть ли 2 массива преобразований -> ponter -> bool? – Slava

+1

@ Слав, это мое понимание. –

2

В данном конкретном случае решение может использовать другой порядок аргументов:

void func(int const n, int *array=NULL, bool const flag=true) { 
    /* print contents of array */ 
} 

Если вы ommit второй параметр логическое значение не может быть неявно преобразовано в указатель (если у вас нет плохого использования 0 как false), поэтому он не сможет скомпилировать (или, по крайней мере, предоставить предупреждение).

void func(int const n, int *array = nullptr, bool const flag=true) { 
     /* print contents of array */ 
} 

int main() 
{ 
    func(0, false); 
} 

warning: converting 'false' to pointer type for argument 2 of 'void func(int, int*, bool)' [-Wconversion-null]

Но в целом это показывает, что вы должны использовать другую технику. Например, используя std::vector вместо необработанного указателя.

typedef std::vector<int> int_vec; 
void func(bool const flag=true, const int_vec &array = int_vec()) { 
     /* print contents of array */ 
} 

int main() 
{ 
    int_vec array {1,2,3,4,5}; 
    func(array); 
} 

error: cannot convert 'int_vec {aka std::vector}' to 'bool' for argument '1' to 'void func(bool, int_vec)'

+0

'false' является (используется?) Действительной константой нулевого указателя. – hvd

+0

@hvd обновленный ответ, спасибо – Slava

+0

Если вы используете 0 в качестве нулевого указателя, вы можете, по крайней мере, получить GCC, чтобы предупредить вас, что вы должны использовать 'nullptr'. – chris

2

Согласно стандарту C++ (4 Стандартные преобразования)

1 Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions. A standard conversion sequence is a sequence of standard conversions in the following order:

— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.

— Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.

— Zero or one qualification conversion.

И

4.12 Булевы конверсии

1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

Так что вызов функции

func(5,array); 

эквивалентно

func(5,array, NULL); 

второй аргумент сначала был преобразован из массива указатель (массив к указателю преобразования), а затем превращают в булево истинные (булевы преобразования).

Таким образом, этот вызов является действительным вызовом функции. Компилятор неявно преобразует аргументы в соответствующие типы.

2

Существует неявное литье в bool. С Visual C++ вы получите предупреждение C4800. В gcc вы можете запросить конкретные предупреждения с параметрами, начинающимися с '-W', например -Wimplicit, чтобы запросить предупреждения о неявных объявлениях. Для получения полной документации см. Options to Request or Suppress Warnings.

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