Почему C++ CLI не имеет аргумента по умолчанию для управляемых типов?

В следующей строке ошибка Default argument is not allowed.

public ref class SPlayerObj{
private:

    void k(int s = 0){ //ERROR
    }
}

Почему C++ не имеет аргумента по умолчанию для управляемых типов?
Я хотел бы знать, есть ли способ это исправить.


person Mohsen Sarkar    schedule 16.03.2013    source источник
comment
В C++ нет управляемых типов, в отличие от C++/CLI; вы должны обновить вопрос   -  person Stephen Lin    schedule 17.03.2013
comment
Ответ, скорее всего, станет чем-то вроде потому что.   -  person sehe    schedule 17.03.2013
comment
@StephenLin Я обновил заголовок   -  person Mohsen Sarkar    schedule 17.03.2013
comment
@sehe на самом деле, по крайней мере, отчасти причина в том, что аргументы по умолчанию С++ оцениваются вызывающей стороной, а не вызываемой, поэтому они должны быть частью метаданных функции для работы с другими языками... С# добавил аргументы по умолчанию и я точно не помню, как они там работают... и в любом случае это более позднее, чем начальная разработка C++/CLI   -  person Stephen Lin    schedule 17.03.2013
comment
У @StephenLin VB.NET они были с самого начала. Речь идет о CLR, а не о каком-то конкретном языке. Кроме того, нет никаких проблем с аргументами по умолчанию, поскольку они в любом случае ref-class специфичны (семантика C++ не имеет к этому ничего отношения), поэтому они могли просто предоставить соответствующую семантику. Однако они этого не сделали.   -  person sehe    schedule 17.03.2013
comment
Что произойдет, если вы измените int на System::Int32?   -  person antonijn    schedule 17.03.2013
comment
@sehe не знал о VB.NET ... но, конечно, они могли бы сделать один и тот же синтаксис с разной семантикой между управляемыми и неуправляемыми типами (и есть много неочевидных угловых случаев с семантикой аргумента C++ по умолчанию, поэтому они вероятно, пришлось бы, даже если бы значения по умолчанию CLR имели семантику оценки вызывающей стороны), но это было бы запутанным и причиной не делать этого... кроме того, аргумент по умолчанию должен был бы быть чем-то, что также может быть оценено другим языком ( или, по крайней мере, понимается его компилятором), что также исключает множество случаев   -  person Stephen Lin    schedule 17.03.2013
comment
Однако идея @Antonijn Intelligence не работает.   -  person Mohsen Sarkar    schedule 17.03.2013
comment
(Значения по умолчанию C++ могут быть произвольными функциями, и они оцениваются вызывающей стороной перед вызовом функции: на самом деле вызывающая сторона даже не знает, используется ли аргумент по умолчанию или нет... в исходном объявлении даже не нужно объявлять это как таковое, если это делает последующее объявление в единице перевода вызывающей стороны.)   -  person Stephen Lin    schedule 17.03.2013
comment
В C++/CLI для управляемых типов нет необязательных параметров. Это может вас заинтересовать: stackoverflow.com/questions/4974237/   -  person antonijn    schedule 17.03.2013
comment
@StephenLin Ты не говоришь мне ничего нового. Кроме того, они могли бы сделать так, чтобы один и тот же синтаксис имел различную семантику между управляемыми и неуправляемыми типами... но это сбило бы с толку и стало бы причиной не делать этого: это полностью противоречит практически всему, что касается сути дизайна С++/командная строка. Дело спорное.   -  person sehe    schedule 17.03.2013
comment
@sehe, ну нет, C++/CLI имеет разную семантику для собственных и управляемых типов, но почти всегда с разным параллельным синтаксисом. то есть template против generic, * против ^, & против %. Следует признать, что синтаксис деструктора перегружен для выполнения двух разных задач, но это скорее исключение, чем правило. Принятый ответ в основном делает то же самое: аргументы по умолчанию С++ в основном похожи на templates, а аргументы по умолчанию CLR похожи на generics, поскольку первые не существуют после времени компиляции, а последние...   -  person Stephen Lin    schedule 17.03.2013
comment
@sehe, так что это действительно то же самое, что и решение не использовать повторно ключевое слово template для generics; они внешне похожи, но имеют разную семантику, поэтому повторное использование одного и того же синтаксиса без устранения двусмысленности было бы неуместным.   -  person Stephen Lin    schedule 17.03.2013
comment
@sehe, если честно, наиболее последовательным было бы разрешить аргументы по умолчанию для управляемых типов, но разрешить их использование только в C++/CLI, используя ту же семантику, что и аргументы по умолчанию C++, подобно тому, как templates over управляемые типы возможны, но не понимаются кодом, отличным от C++/CLI, но я понимаю, почему они этого не сделали.   -  person Stephen Lin    schedule 17.03.2013
comment
@StephenLin, я согласен :)   -  person sehe    schedule 17.03.2013


Ответы (3)


У него есть необязательные аргументы, просто они не выглядят так же, как синтаксис C++. Необязательные аргументы — это проблема языкового взаимодействия. Он должен быть реализован языком, который делает вызов, он генерирует код, который фактически использует аргумент по умолчанию. Что является сложной проблемой для языка, который был разработан для облегчения взаимодействия, такого как C++/CLI, вы, конечно, не знаете, на каком языке будет выполняться вызов. Или если у него даже есть синтаксис для необязательных аргументов. Например, язык С# не работал до версии 4.

И если язык поддерживает это, как этот компилятор узнает значение по умолчанию. Примечательно, что VB.NET и C# v4 выбрали разные стратегии, VB.NET использует атрибут, а C# использует modopt.

Вы можете использовать атрибут [DefaultParameterValue] в C++/CLI. Но вы не должны, результат непредсказуем.

person Hans Passant    schedule 16.03.2013
comment
Знаете ли вы, исправлено ли [DefaultParameterValue] в VS2012? - person Mohsen Sarkar; 17.03.2013
comment
С++/CLI не изменился с VS2005. - person Hans Passant; 17.03.2013

В дополнение к точному ответу от Hans Passant, ответу на вторую часть о том, как это исправить, вы можете используйте несколько методов с одним и тем же именем, чтобы имитировать случай аргумента по умолчанию.

public ref class SPlayerObj {
  private:
    void k(int s){ // Do something useful...
    }
    void k() { // Call the other with a default value 
       k(0);
    }
}
person holroy    schedule 07.01.2015
comment
Итак, это так же дерьмово, как Java! - person Brain2000; 28.12.2018

Альтернативное решение — использовать [OptionalAttribute] вместе с типизированным параметром Nullable<int>. Если параметр не указан вызывающей стороной, это будет nullptr.

void k([OptionalAttribute]Nullable<int>^ s)
{
    if(s == nullptr)
    {
        // s was not provided
    }
    else if(s->HasValue)
    {
        // s was provided and has a value
        int theValue = s->Value;
    }
}
// call with no parameter
k();
// call with a parameter value
k(100);
person Aaron Hudon    schedule 30.03.2017
comment
Здесь много бокса. Кстати, вы можете использовать s->HasValue, даже если это nullptr. Это намного быстрее. - person Brain2000; 28.12.2018