zoukankan      html  css  js  c++  java
  • ObjectC可变参数函数的定义方法

    一.C语言的可变参数函数实现

    首先看一下C语言中的可变参数是怎么实现的:

    C语言支持va函数,作为C语言的扩展--C++同样支持va函数,但在C++中并不推荐使
    用,C++引入的多态性同样可以实现参数个数可变的函数。不过,C++的重载功能毕
    竟只能是有限多个可以预见的参数个数。比较而言,C中的va函数则可以定义无穷多
    个相当于C++的重载函数,这方面C++是无能为力的。va函数的优势表现在使用的方
    便性和易用性上,可以使代码更简洁。C编译器为了统一在不同的硬件架构、硬件平
    台上的实现,和增加代码的可移植性,提供了一系列宏来屏蔽硬件环境不同带来的
    差异。

    ANSI C标准下,va的宏定义在stdarg.h中,它们有:va_list,va_start(),va_ar
    g(),va_end()。

    // 例2:求任意个自然数的平方和:

     1 int SqSum(int n1, ...)
    2
    3 {
    4
    5 va_list arg_ptr;
    6
    7 int nSqSum = 0, n = n1;
    8
    9 va_start(arg_ptr, n1);
    10
    11 while (n > 0)
    12
    13 {
    14
    15 nSqSum += (n * n);
    16
    17 n = va_arg(arg_ptr, int);
    18
    19 }
    20
    21 va_end(arg_ptr);
    22
    23 return nSqSum;
    24
    25 }


    // 调用时

    int nSqSum = SqSum(7, 2, 7, 11, -1);

    可变参数函数的原型声明格式为:

    type VAFunction(type arg1, type arg2, … );

    参数可以分为两部分:个数确定的固定参数和个数可变的可选参数。函数至少需要
    一个固定参数,固定参数的声明和普通函数一样;可选参数由于个数不确定,声明
    时用"…"表示。固定参数和可选参数公同构成一个函数的参数列表。

    借助上面这个简单的例2,来看看各个va_xxx的作用。

    va_list arg_ptr:定义一个指向个数可变的参数列表指针;

    va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个
    可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一
    个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声
    明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, c
    har c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是
    va_start(arg_ptr, c)。

    va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为ty
    pe,并使指针arg_ptr指向参数列表中下一个参数。

    va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表
    指针,将dest初始化为src。

    va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。说明:指针arg_pt
    r被置无效后,可以通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_st
    art() / va_copy()后,必须得有相应的va_end()与之匹配。参数指针可以在参数列
    表中随意地来回移动,但必须在va_start() … va_end()之内。

    二.ObjectC的可变参数函数的定义

    其实ObjectC要实现函数的参数数目可变,可以有两种方法,最简单也是最容易想到的一种就是利用数组来传递参数.

    另外一种就是定义可变参数的函数了.

    相对应ObjectC的语法规则,可变参数定义的方法也有所不同.

    自己的一个OBjectC 的示例

     1 - (void)initWithMultiColumnProperties:(NSArray *)ColumnProperties, ...
    2
    3 {
    4
    5
    6
    7 va_list arg_ptr;
    8
    9 if (ColumnProperties)
    10
    11 {
    12
    13 for (ColumnProperty * aRowColumnProp in ColumnProperties)
    14
    15 {
    16
    17 UILabel *column1 = [[UILabel alloc]init];
    18
    19 [self initColumn:column1 WithProperty:aRowColumnProp];
    20
    21 [self addSubview:column1];
    22
    23 [column1 release];
    24
    25 }
    26
    27
    28
    29 va_start(arg_ptr, ColumnProperties);
    30
    31
    32
    33 NSArray * RowProp = va_arg(arg_ptr, id);
    34
    35 while (RowProp)
    36
    37 {
    38
    39 for (ColumnProperty * aRowColumnProp in RowProp)
    40
    41 {
    42
    43 UILabel *column = [[UILabel alloc]init];
    44
    45 [self initColumn:column WithProperty:aRowColumnProp];
    46
    47 [self addSubview:column];
    48
    49 [column release];
    50
    51 }
    52
    53
    54
    55 RowProp = va_arg(arg_ptr, id);
    56
    57 }
    58
    59
    60
    61 }
    62
    63
    64
    65 }


    实现过程中遇到一些问题,比如可变参数有不同的类型时,需要特别注意.当为C语言基本类型(如int,float等)调用va_arg(,)会有错误,需要将这些基本类型封装为ObjectC的对象类型.

  • 相关阅读:
    【Yom框架】漫谈个人框架的设计之一:是IRepository还是IRepository<T>?
    【NET】Winform用户控件的初步封装之列表页控件
    【C#】Smtp发送邮件
    c# http请求封装
    js 时区转换
    c# http请求接口
    netcore 中间件记录日志
    netcore 调用log4net
    netcore 从api下载文件并直接返回
    netcore 从api下载文件到本地
  • 原文地址:https://www.cnblogs.com/woainilsr/p/2342527.html
Copyright © 2011-2022 走看看