【问题标题】:how to skip Default Arguments C++?如何跳过默认参数 C++?
【发布时间】:2011-11-24 22:03:58
【问题描述】:

我必须编写带有两个默认参数的构造函数。

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

向我提供了调用构造函数并为arg1arg2 提供值的场景,而arg3 预计将使用默认值。然后实例化另一个对象,并为arg1arg3 赋予一个值,并且预计将使用arg2 的默认值。 现在的问题是,您“不能跳过”默认参数是我从文本和在线阅读的内容。据说是根据重载的可能性对默认参数进行排序,但是该场景使用了一个默认参数,而另一个没有使用。这个问题的提示告诉我重新排序参数/参数。但是,我做的再多的重新排序似乎都无法解决这个问题。

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

那么如何做到这一点呢?我被难住了,为此有点疯狂:(

【问题讨论】:

  • 您不能在 C++ 中使用单个函数定义来执行此操作。鉴于任何其他解决方案都违反了您所拥有的奇异约束,您想要的都是不可能的。也许您可以使用其他语言。
  • 你不能使用vectorobject's? This way you could pass what you wanted and sort what wasn't passed based on null` 条目。
  • 是否允许额外的构造?例如like this
  • 你可以使用额外的函数(不是构造函数)吗?

标签: c++ parameters default


【解决方案1】:

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

我能想到这个要求的唯一原因是可选参数具有相同的类型。在这种情况下,您会陷入困境,您需要查看 named constructor 和/或 named parameter 成语。

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

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

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

【讨论】:

  • 这些是一些非常好的成语,感谢分享链接。 Stack Overflow 的一大优点是你可以随机阅读线程并学习一些很酷的东西 :) +1
【解决方案2】:

如果允许在第二个参数没有值时传递一个空的 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!"));
}

不漂亮,我知道...

【讨论】:

    【解决方案3】:

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

    #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

    【讨论】:

      【解决方案4】:

      现在你可以使用 std::bind 来做这种操作,或者在 c++14/17 中你可以使用 lambda 函数来完成同样的操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-05
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-01
        相关资源
        最近更新 更多