设为首页 加入收藏

TOP

建议15:尽量不要使用可变参数(2)
2013-10-07 14:47:25 来源: 作者: 【 】 浏览:57
Tags:建议 尽量 不要 使用 可变 参数

建议15:尽量不要使用可变参数(2)

(1)缺乏类型检查,类型安全性无从谈起。“省略号的本质是告诉编译器‘关闭所有检查,从此由我接管,启动reinterpret_cast’”,强制将某个类型对象的内存表示重新解释成另外一种对象类型,这是违反“类型安全性”的,是大忌。

例如,自定义的打印函数。

  1. void UserDefinedPrintFun(char* format, int i, ...)  
  2. {  
  3.      va_list arg_ptr;  
  4.      char *s = NULL;  
  5.      int *i = NULL;  
  6.      float *f = NULL;  
  7.  
  8.      va_start(arg_ptr, i);  
  9.      while(*format!='\0')  
  10.      {  
  11.          format++;  
  12.          if(*(format-1)=='%' && *format=='s')  
  13.         {  
  14.           s = va_arg(arg_ptr, char*);  
  15.             …… // 输出至屏幕  
  16.         }  
  17.         else if(*(format-1)=='%' && *format=='d')  
  18.         {  
  19.           i = va_arg(arg_ptr, int*);  
  20.             …… // 输出至屏幕  
  21.         }  
  22.         else if(*(format-1)=='%' && *format=='f')  
  23.         {  
  24.           f = va_arg(arg_ptr, float*);  
  25.             …… // 输出至屏幕  
  26.         }  
  27.     }  
  28.  
  29.     va_end(arg_ptr);  
  30.     return;  

如果采用下面三种方法调用,合法合理:
  1. UserDefinedPrintFun ("%d", 2010);  // 结果2010  
  2. UserDefinedPrintFun ("%d%d", 2010,2011);  // 结果20102011  
  3. UserDefinedPrintFun ("%s%d", "Hello", 2012); // 结果Hello2012 

但是,当给定的格式字符串与参数类型不对应时,强制转型这个“怪兽”就会被唤醒,悄悄地毁坏程序的安全性,这可不是什么高质量的程序,如下所示:
  1. UserDefinedPrintFun ("%d", 2010.80f);  
  2. // 结果2010  
  3. UserDefinedPrintFun ("%d%d", "Hello", 2012);  
  4. // 结果150958722015(这是什么结果???) 

(2)因为禁用了语言类型检查功能,所以在调用时必须通过其他方式告诉函数所传递参数的类型,以及参数个数,就像很多人熟知的printf()函数中的格式字符串char* format。这种方式需要手动协调,既易出错,又不安全,上面的代码片段已经充分说明了这一点。

(3)不支持自定义数据类型。自定义数据类型在C++(www.cppentry.com)中占有较重的地位,但是长参数只能传递基本的内置类型。还是以printf()为例,如果要打印出一个Student类型对象的内容,对于这样的自定义类型,该用什么格式的字符串去传递参数类型呢?如下所示:

  1. class Student  
  2. {  
  3. public:  
  4.     Student();  
  5.     ~ Student();  
  6. private:  
  7.   string m_name;  
  8.     char   m_age;  
  9.     int    m_scoer;  
  10. };  
  11.  
  12. Student XiaoLi;  
  13. printf(format, XiaoLi);  // format应该是什么呢 

上述缺点足以让我们有了拒绝使用C风格可变参数的念头,何况C++(www.cppentry.com)的多态性已经为我们提供了实现可变参数的安全可靠的有效途径呢!如下所示:
  1. class PrintFunction  
  2. {  
  3. public:  
  4.     void UserDefinedPrintFun(int i);  
  5.     void UserDefinedPrintFun(float f);  
  6.     void UserDefinedPrintFun(int i, char* s);  
  7.     void UserDefinedPrintFun(float f, char* s);  
  8. private:  
  9.      ……  
  10. }; 

虽然上述设计不能像printf()函数那样灵活地满足各种各样的需求,但是可以根据需求适度扩充函数定义,这样不仅能满足需求,其安全性也是毋庸置疑的。舍安全而求危险,这可不是明白人所为。如果还对printf()的灵活性念念不忘,我告诉大家,有些C++(www.cppentry.com)库已经使用C++(www.cppentry.com)高级特性将类型安全、速度与使用方便很好地结合在一起了,比如Boost中的format库,大家可以尝试使用。

请记住:

编译器对可变参数函数的原型检查不够严格,所以容易引起问题,难于查错,不利于写出高质量的代码。所以应当尽量避免使用C语言方式的可变参数设计,而用C++(www.cppentry.com)中更为安全的方式来完美代替之。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇建议17:提防隐式转换带来的麻烦.. 下一篇建议15:尽量不要使用可变参数(1..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: