问题 如何跳过默认参数C ++?


我必须用两个默认参数编写构造函数。

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

我提供了调用构造函数并给出值的场景 arg1 和 arg2 和 arg3 预计使用默认值。然后实例化另一个对象并给出一个值 arg1 和 arg3,和默认值 arg2 预计将被使用。     现在的问题是,你“不能跳过”默认参数是我从文本和在线阅读。它的意思是从默认参数的重载中排序,但是场景使用了一个默认参数,而另一个则没有。这个问题的提示告诉我重新排序参数/参数。但是,我所做的任何重新排序似乎都无法解决此问题。

此外,不能使用重载的构造函数。这必须由一个构造函数完成。

那怎么会这样呢?我很难过,有点疯狂:(


3174
2017-11-24 22:03


起源

您不能在单个函数定义的C ++中执行此操作。鉴于任何其他解决方案都违反了你所拥有的奇怪限制,你想要的是不可能的。也许你可以使用不同的语言。 - CB Bailey
这是家庭作业吗? - xmoex
你能用吗? vector 的 object's? This way you could pass what you wanted and sort what wasn't passed based on null`条目。 - MoonKnight
你是否允许其他结构?例如 喜欢这个 - Vlad
可能重复 我怎样才能清楚地指定我传递的参数? - Pubby


答案:


此外,不能使用重载的构造函数。这必须由一个构造函数完成。

我能想到这个要求的唯一原因是可选参数具有相同的类型。在那种情况下,你被困住了,你会想要调查 命名构造函数 和/或 命名参数 成语。

否则,只需定义额外的构造函数。这可能涉及一些重复。默认值。

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

Foo(int arg1, int arg3)
{
    construct(arg1, "arg2", arg3);
}

8
2017-11-24 22:09



这些是非常好的习语,感谢分享链接。关于Stack Overflow的一个很棒的事情是,你可以随机细读线程并学习一些很酷的东西:) +1 - Chris Parton


如果在第二个参数没有值时允许传递一个空的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
2017-11-24 23:10





特殊限制,必须只有一个构造函数。这是我能想到的最接近的:

#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,这会生成警告,因为从字符串文字转换为非const char* 被弃用且不明智。但这是你要求的,并修复它以便 char* 参数和数据成员是 const char* 很容易。

一个重要的缺点是,这并不能阻止你写作 Foo(1,2,3)。要在编译时检查一下,我认为你需要多个构造函数。要在运行时检查它,可以将第三个参数放入另一个类中, DefaultOrInt,哪里 Default 是一种仅用于此目的的类型,仅支持一个用作默认值的值 arg3。然后如果 arg2.isInt() 是的,检查 arg3.isInt() 是假的,如果不扔 logic_error


2
2017-11-24 22:59





现在你可以使用 的std ::绑定 要做这种操作或在c ++ 14/17中你可以使用lambda函数并完成相同的操作。


1
2018-01-10 09:00