Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数中的参数数目未知_C++_Argument Passing_Variadic Functions - Fatal编程技术网

C++ 函数中的参数数目未知

C++ 函数中的参数数目未知,c++,argument-passing,variadic-functions,C++,Argument Passing,Variadic Functions,我有一个班级成员: LineND::LineND(double a ...) { coefficients.push_back(a); va_list arguments; va_start(arguments, a); double argValue; do { argValue = va_arg(arguments, double); coefficients.push_back(argValue); }

我有一个班级成员:

LineND::LineND(double a ...)
{
    coefficients.push_back(a);
    va_list arguments;
    va_start(arguments, a);
    double argValue;
    do
    {
        argValue = va_arg(arguments, double);
        coefficients.push_back(argValue);
    }while(argValue != NULL);   // THIS IS A PROBLEM POINT!
    va_end(arguments);
}
我不知道将使用多少参数。我需要获取每个参数,并将其放入名为
系数的向量中。我该怎么做?我理解,在这种情况下,
while(argValue!=NULL)
语句是不正确的。例如,我不能使用此签名:

LineND::LineND(int numArgs, double a ...)
要像这样更改条件,请执行以下操作:

while(argValue != numArgs);

关键是我不能更改方法的签名。需要用另一种方式来解决这个问题。

在C++中,变量的参数被严重地混淆了,并且有充分的理由。其中一个原因是无法知道列表的结束位置,因此如果无法更改函数的签名,则必须指定某种类型的sentinel值来指示列表的结束位置。如果这两件事都做不到,你就完了。

在这种情况下,你无法确定代码中的参数数量。您必须让该函数的调用方将
double
s的数量传递给您(我假设第一个
a
参数不包含参数的数量)。例如:

然后情况就变了

while (a--) { ... }
在C++11中,可以使用两个更好的设备来传递未指定数量的双倍数

  • 请注意,两者之间存在差异;THO在转发时出现了一些问题,即代码“> {…}/<代码>不是C++中的表达式。后者会导致代码膨胀,因为它会为参数类型的每个组合生成一个函数


    在C++03中,您只能使用助手对象(如库提供的对象)来传递未知数量的参数。

    您应该重写该方法以获取
    std::initializer\u list

    如果您不能这样做,并且不能添加
    count
    参数,那么修复方法是采用一个终止参数列表的sentinel值,例如
    0.0
    NaN
    (或在函数上下文中没有意义的任何值)


    例如,采用可变数量指针的函数使用
    NULL
    作为哨兵值;采用结构列表的函数采用0初始化的结构作为哨兵。这在C API中相当常见;参见此处给出的示例是execl(“/bin/sh”、“sh”、“-c”、“date”、(char*)NULL)

    将参数列表的前两个参数设置为参数的实际计数。

    变量参数列表有几个缺点:

    • 打电话的人可以传递他们想要的任何东西
    • 如果传递了非POD对象,则调用未定义的行为
    • 您不能依赖参数的数量(调用者可能会出错)
    • 您将大量责任放在客户身上,您希望客户能够更轻松地使用库代码(实际示例:格式字符串bug/-errors)
    与可变模板相比:

    • 编译时列表大小已知
    • 类型在编译时是已知的
    • 你有责任做事情,而不是你的客户,这是应该做的
    例如:

    void pass_me_floats_impl (std::initializer_list<float> floats) {
        ...
    }
    
    他现在可以做到:

    pass_me_floats ();
    pass_me_floats (3.5f);
    pass_me_floats (1f, 2f, 4f);
    
    但他不能这样做:

    pass_me_floats (4UL, std::string());
    
    因为这将在pass\me_uufloats-function中发出编译错误

    如果您至少需要,比如说,两个参数,那么就这样做:

    template <typename ...ArgsT>
    void pass_me_floats (float one, float two, ArgsT... rest) {}
    
    模板
    无效传递\我\浮动(浮动一,浮动二,ArgsT…rest){}
    
    当然,如果你想让它成为一个完整的内联函数,你也可以

    template <typename ...ArgsT>
    void pass_me_floats (ArgsT... rest) {
        std::array<float, sizeof...(ArgsT)> const floaties {rest...};
    
        for (const auto f : floaties) {}
    }
    
    模板
    无效通行证浮动(ArgsT…rest){
    数组常量浮动{rest…};
    对于(const auto f:floaties){}
    }
    
    Ok,因此您不能更改函数的签名。你能至少添加到类和函数体中吗?非常感谢你的详细解释。我不太确定我是否理解“
    {…}
    不是表达式”。你是说类似的东西吗?编辑:OOP,它们有一个太老的G++:@ PrHeNeLe:我指的是通过(注意到警告实际上是一个C++ C++标准的错误而不会通过新的GCC)的东西:那个<代码> {…} /CODE只是一个用于初始化的特殊语法,而不是一个表达式本身(在C++ GROAMR)中。您无法方便地将其保存到变量中以备以后使用,也无法从中推断类型等。您的示例仅在初始化局部变量时使用最普通的初始化器列表,从而避免了所有问题。有关另一个不一致性,请参阅。
    template <typename ...ArgsT>
    void pass_me_floats (float one, float two, ArgsT... rest) {}
    
    template <typename ...ArgsT>
    void pass_me_floats (ArgsT... rest) {
        std::array<float, sizeof...(ArgsT)> const floaties {rest...};
    
        for (const auto f : floaties) {}
    }