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的对象类型.

posted @ 2012-02-08 13:00  woainilsr  阅读(1793)  评论(0编辑  收藏  举报