含有可变形参的函数

为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:

  • 如果所有的实参类型相同,可以传递一个名为 initializer_list 的标准库类型。
  • 如果实参的类型不同,我们可以编写可变参数模板。

initializer_list 形参

如果函数的实参数量未知但是全部实参的类型都相同,可以使用 initializer_list 类型的参数:

initializer_list提供的操作
initializer_list<T> lst; 默认初始化T类型元素的空列表
initializer_list<T> lst{a,b,c...}; lst的元素数量和初始值一样多,lst的元素是对应初始值的副本,列表中的元素是const

lst2(lst)

lst2=lst

拷贝或赋值一个initializer_list对象不会拷贝列表中的元素,拷贝后,原始列表和副本共享元素
lst.size() 列表中的元素数量
lst.begin() 返回指向lst中首元素的指针
lst.end() 返回指向lst中尾元素下一位置的指针

initializer_list 是一种模板类型,定义initializer_list 对象时,必须说明列表中所含元素的类型:

    initializer_list<string> ls;//initializer_list的元素类型是string
    initializer_list<int> li;//initializer_list的元素类型是int

initializer_list 对象中的元素永远是常量值,无法改变initializer_list 对象中元素的值。

使用如下的形式编写输出错误信息的函数,使其可以作用于可变数量的实参:

void error_msg(initializer_list<string> il)
{
    for (auto beg = il.begin(); beg != il.end(); ++beg)
        cout << *beg << " ";
    cout << endl;
}

begin() 成员提供一个指向列表首元素的指针,end()成员提供一个指向列表尾后元素的指针。

函数首先初始化beg令其表示首元素,然后依次遍历列表中的每个元素。

在循环体中,解引用beg以访问当前元素并输出它的值。

向 initializer_list 形参中传递一个值得序列,则必须把序列放在一对花括号内:

    //expected和actual是string对象
    if (expected != actual)
        error_msg({ "functionX",expected,actual });
    else
        error_msg({ "functionX","okay" });

上面代码调用同一个函数 error_msg,两次调用传递的参数量不同:

  • 第一次调用传入了三个值
  • 第二次调用只传入了两个

含有 initializer_list 形参的函数也可以同时拥有其他形参,调试系统可以可能有个名为 ErrCode 的类用来表示不同类型的错误,改写程序使其包含一个 initializer_list 形参和一个 ErrCode 形参:

void error_msg(ErrCode e, initializer_list<string> il)
{
    cout << e.msg() << ": ";
    for (const auto& elem : il)
        cout << elem << " ";
    cout << endl;
}

因为 initializer_list 包含 begin 和 end 成员,所以可以使用范围 for 循环处理其中的元素,遍历传给 li 形参的列表值,每次迭代访问一个元素。

调用这个版本的 error_msg 函数,需要额外传递一个 ErrCode 实参:

    if (expected != actual)
        error_msg(Error(42),{ "functionX",expected,actual });
    else
        error_msg(Error(0) ,{ "functionX","okay" });

省略符形参

省略符形参应该仅仅用于C和C++通用的类型,大多数类类型的对象在传递给省略形参时都无法正确拷贝。

省略符形参只能出现在形参列表的最后一个位置,它的形式无外乎以下两种:

void foo(parm_list, ...);
void foo(...);
  • 第一种形式指定了 foo 函数的部分形参的类型,对应于形参的实参将会执行正常的类型检查。
  • 省略符所对应的实参无需类型检查。
  • 在第一种形式中,形参声明后面的逗号是可选的。

 

posted @ 2019-07-13 11:58  CodeWithMe  阅读(314)  评论(0)    收藏  举报