как пропустить Аргументы по умолчанию C ++? - PullRequest
11 голосов
/ 25 ноября 2011

Я должен написать конструктор с двумя параметрами по умолчанию.

func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example

Мне предоставляется сценарий, в котором вызывается конструктор, и значение присваивается arg1, а arg2 и arg3 должны использовать значение по умолчанию. Затем создается другой объект, и значение присваивается arg1 и arg3, и ожидается, что будет использоваться значение по умолчанию для arg2. Теперь проблема в том, что вы не можете пропустить параметры по умолчанию, это то, что я читаю из текста и онлайн. Это говорит о том, что порядок параметров по умолчанию можно перегрузить, но в сценарии используется один параметр по умолчанию, а другой - нет. Советы по этому вопросу говорят мне, чтобы изменить порядок параметров / аргументов. Тем не менее, никакие повторные заказы, которые я сделал, похоже, не смогли решить эту проблему.

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

Так как же это сделать? Я в замешательстве и схожу с ума по этому поводу :(

Ответы [ 4 ]

8 голосов
/ 25 ноября 2011

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

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

В противном случае просто определите дополнительный конструктор. Это может повлечь за собой некоторое дублирование в отношении. значения по умолчанию.

Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1)
{
    construct(arg1, arg2, arg3);
}

Foo(int arg1, int arg3)
{
    construct(arg1, "arg2", arg3);
}
2 голосов
/ 25 ноября 2011

Если вам разрешено передавать пустую C-строку, когда у вас нет значения для второго параметра, вы можете использовать вспомогательный функтор, который проверит arg2 и вернет значение по умолчанию, если оно пустое.Примерно так:

#define DEFAULT_ARG "arg2"

struct helper_class {
    char* operator()(char* arg)
    {
        if (*arg) return arg; else return DEFAULT_ARG;
    }
} helper;

class func {
    public:
    func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {}
};

int main()
{
    func f1(42, helper(""), 9001);   // default 2nd argument
    func f2(42, helper("Its over 9000!"));
}

Не очень, я знаю ...

2 голосов
/ 25 ноября 2011

Особое ограничение, что должен быть только один конструктор. Вот самое близкое, о чем я могу подумать:

#include <iostream>

// cheap and cheerful Boost.Variant
struct StringOrInt {
    char *s;
    int i;
    bool is_string;
    StringOrInt(char *s) : s(s), i(0), is_string(true) {}
    StringOrInt(int i) : s(0), i(i), is_string(false) {}
    bool isInt() { return !is_string; }
    int asInt() { return i; }
    char *asString() { return s; }
};

struct Foo {
    int m1;
    char *m2;
    int m3;
    Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) {
        if (arg2.isInt()) {
            arg3 = arg2.asInt();
            arg2 = "arg2";
        }
        m2 = arg2.asString();
        m3 = arg3;
    }
    void print() {
        std::cout << m1 << " " << m2 << " " << m3 << "\n";
    }
};

int main() {
    Foo(1, "HelloWorld").print();
    Foo(1, 2).print();
}

Обратите внимание, что с GCC это генерирует предупреждения, поскольку преобразование строкового литерала в неконстантный char* устарело и неразумно. Но это то, что вы просили, и исправить это так, чтобы параметры char* и элемент данных были const char*, достаточно просто.

Существенным недостатком является то, что это не мешает вам писать Foo(1,2,3). Чтобы проверить это во время компиляции, я думаю, вам нужно несколько конструкторов. Чтобы проверить это во время выполнения, вы можете преобразовать третий параметр в другой класс, DefaultOrInt, где Default - это тип, используемый только для этой цели, поддерживая только одно значение, используемое в качестве значения по умолчанию arg3. Тогда, если arg2.isInt() верно, проверьте arg3.isInt() ложно, а если нет, бросьте logic_error.

1 голос
/ 10 января 2018

Прямо сейчас вы можете использовать std :: bind для выполнения операций такого типа или в C ++ 14/17 вы можете использовать лямбда-функцию и выполнить то же самое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...