2010-08-17 3 views

ответ

14

, если у вас было void func(int a = 0, int b);, как бы вы указали использовать параметр по умолчанию при вызове этой функции?

+6

Я знаю, что вы не можете в C++, но другие языки обрабатывают это с помощью 'func (, some_val_for_b)' или именованных параметров. –

+1

@ Доминистский Роджер: для меня это выглядит действительно уродливо. – dierre

+2

@ Dominic Rodger, ну, C++ - нет. Если вы хотите, вы можете подать в суд на Stroupstroup: P –

-1

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

+1

Что делает начало списка настолько принципиально отличным от конца списка? Списки симметричны! –

+2

Да, но представьте себе: void func (int a, int b = 0, int c, int d = 0); Что вы делаете, когда вызываете func (1, 2, 3); –

+0

И какой конец списка, собственно, 'b' on? –

1

Просто, чтобы дополнить ответ @ tenfour. C++ FAQ В Lite есть тема, описывающая named parameters, и я думаю, что тема затрагивает вашу проблему в некоторой степени.

5

Потому что именно так разработан язык.

Более интересный вопрос: какие альтернативы?

Предположим, у вас есть void f(A a = MyA, B b);

  • Placeholder/пустой аргумент: f(_, abee) или f(, abee)
  • Именованные аргументы (например, в Python): f(b = abee)

Но те тонкости, и, конечно, не надо, потому что в отличие от Python C++ поддерживает перегрузку функции:

  • void f(A a, B b);
  • void f(B b) { f(MyA, b); }

и, таким образом, аргументы по умолчанию не нужны ... особенно с учетом того, что существуют проблемы при использовании ОО-кода, потому что аргументы по умолчанию статически разрешены (во время компиляции)

struct Base 
{ 
    virtual void func(int g = 3); 
}; 

struct Derived 
{ 
    virtual void func(int g = 4); 
}; 

int main(int argc, char* argv[]) 
{ 
    Derived d; 
    d.func(); // Derived::func invoked with g == 4 

    Base& b = d; 
    b.func(); // Derived::func invoked with g == 3 (AH !!) 
} 

EDIT: по названным параметрам ->

функция может быть эмулирована с использованием функциональных объектов.

class Func 
{ 
public: 
    Func(B b): mA(MyA), mB(b) {} 

    A& a(A a) { mA = a; } 
    B& b(B b) { mB = b; } 

    void operator()() { func(mA, mB); } 
private: 
    A mA; 
    B mB; 
}; 

int main(int argc, char* argv[]) 
{ 
    A a; B b; 
    Func(b)(); 
    Func(b).a(a)(); 
} 

В случае, если вы не хотите копировать аргументы, у вас есть возможность использовать ссылки/указатели, хотя это может усложниться.

Это удобная идиома, когда у вас есть множество дефолтов без реального порядка приоритета.

+0

Перегрузка функций не помогает, если 'A' и' B' являются одинаковыми типами ... –

+0

@ Oli: why? учитывая первый прототип 'func', ясно, что если есть только один параметр, то для первого параметра следует использовать значение по умолчанию, независимо от их типа. Вещи становятся волосатыми, когда у вас есть два значения по умолчанию:) В общем, названные параметры - единственное, что может решить проблему, и что здорово, что они являются решением для компиляции. –

+0

Да, вы правы. Я думал, вы используете перегрузку, чтобы устранить «func (A a, B b)», «func (B b)» и «func (A a)». –

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