经验分享 从C到C++(二)

开发 后端
本文介绍的是从C到C++我们应该学习哪些内容,让你轻轻松松完成从C到C++的转变。希望对你有帮助,一起来看。

C++技术固然是很时髦的,许多C用户都想在尽可能短的时间内为自己贴上C++的标签。介绍C++的书很多,但只有那些已经侥幸入门的用户才偶尔去翻翻,仍有不少在C++门口徘徊的流浪汉。

本文只针对C用户,***是一位很不错的老用户(譬如他在遇到最简单的问题时都尝试着使用指针),通过一些C和更好的C++(本文用的是Borland C++3.1版本)例程介绍有关C++的一些知识,让读者朋友们“浅入深出”,轻轻松松C to C++!

二、挑战#define

#define是C提供的一条很有用的指令,但在C++中,很有可能杜绝宏指令的使用。

1 .const宏指令允许用户指定某一标识符的值作为一个常量,

如:#define PI 3. 1415926

它也可以用来定义字符串:#define HZK16 "HZK16F"以下使用可以通过:

 

  1. cout << "PI is“<<PI;  
  2. cout << "Filename: "<< HZK16;  

 

但宏毕竟不是一个合法的对象,虽然它伪装得很***。C++为用户提供了常量修饰符const,可以指定某个对象的值为常量。它阻止用户对其进行赋值或其它副作用,

类似于上例:

  1. const float PI=3.1415926;  
  2. char*const HZK16="HZK16F";  
  3. PI = 3. 14; //error  
  4. HZK16="HZK16K"//error: Cannot modify a const object  

但对于指针的处理似乎有些复杂,例如以下使用却又合法:

  1. HZK16[5]=’r’; //ok HZK16 ="HZK16K" 

 

清楚地了解const修饰的范围很有必要,如下是声明形式与相应含义:

  1. char*const cpl="I love you!“; //const修饰’*’,cp1是一个指向字符的指针常量  
  2. const char*cp2="I hate you!“; //const修饰’char' cp2是一个指向字符常量的指针  
  3. const char*const cp3="Get the hell out of here!“; // const分别修饰’char’和’*’, 

 

cp3是一个指向字符常量的指针常量,因此,以下使用仍合法:

  1. strcpy(cpl "Oh no...“);  
  2. cp2++; 

 

因为cpl只管盯住某一处的地址不放,而阻止其中的内容不被改写则不是它的责任,cp2则恰恰相反,它不允许你修改其中的内容,却可以被你指来指去(这个下场可能更惨)。只有使用两个修饰符(如cp3)才可能是最保险的办法。

指向const的指针不能被赋给指向非const的指针:

  1. float*p=&PI;  
  2. //error: Cannot convert 'const float*’ to 'float*’  
  3. *p=3.14; 

 

这条限制保证了常量的正当含义。但注意由显式转换所引起的常量间接修改是可能的:

  1. //test08.cpp  
  2. #include <iostream.h>  
  3. void main()  
  4. {  
  5. char * Spy;  
  6. const char * const String = "Yahoo!";  
  7. Spy = (char*)String;  
  8. Spy[5] = '?';  
  9. cout << String;  
  10. }  
  11. 输出结果:Yahoo! 

 

2.内联函数(in line function)

宏在某些场合能得到类似于函数的功能,如下是一个常见的例子:#define ADD (a b) ((a)+(b))

cout<<“1+2=”<它将实现数据求和功能而输出:但我们至少有一打理由拒绝使用它,以下是最明显的:

①宏缺少类型安全检测,如:

  1. ADD ('A' 0. 0l); 

 

这样的调用将被解释为合法,而事实上,很少的用户期望能写出这样的语句;

②宏不会为参数引入临时拷贝,如:

 

  1. #define DOUBLE (x)((x)+(x))  
  2. int i(1);  
  3. cout<<DOUBLE(i++); //prints '3'  

 

③宏不具有地址,例如可能在一个计算器程序中有:

  1. case ' +': Operator = & ADD; 

 

并不能得到合理解释。

采取函数?然而,使用函数并不是最划算的支出,它浪费了宝贵的执行时间。使用过汇编语言的读者可能知道,一般函数执行真正的函数体前后,要做一些现场保护工作,当函数体积很小时,这种冗余的工作量将会远远大于函数本身。

为此,C++提供了关键字inline,当用户希望编译器将某函数的代码直接插入到调用点时,可将其设置成inline函数,即在函数定义时加上关键字inline,如:

 

  1. //test09.cpp  
  2. #include <iostream.h>  
  3. inline int Add (int a int b)  
  4. {  
  5. return a + b;  
  6. }  
  7. void main O)  
  8. {  
  9. cout<<"1+2=“<<Add(1 2);  
  10. }  

主函数将被编译器解释为:

  1. count<<"1+2=“<<{1+2 }; 

 

其行为完全类似于前例的ADD (a b)宏。经验表明,将使用频繁而且体积很小的函数声明为inline是明智的。

3.函数重载(overload)

在实际数据求和操作时,如上节内容中提供的Add()函数是远远不够的,你不得不再添加一些其它代码,如:

 

  1. double AddDouble(double a double b)  
  2. {  
  3. return a + b;  
  4. }  
  5. float AddFloat (float a float b )  
  6. {  
  7. return a + b;  
  8. }  

 

特别地,在C++中你可以玩弄名字的技巧,将以上的AddDouble AddFloat皆取名为Add,如:

  1. double Add(double a double b)  
  2. {  
  3. return a + b;  

尽管放心,编译器会安全地为不同的调用形式找到相应的函数原型。如:

  1. double a b;  
  2. Add(f 2); //int Add(int int)  
  3. Add (a b); //double Add (doubledouble)  

 

这样,不同的函数拥有相同的函数名,即函数重载。函数重载以及后面的模板、虚函数机制形成了“一个接口,多种功能”的特性,即多态性(polymorphism),它是面向对象(OO)的技术之一。

在使用重载机制时,C++提出了许多防止二义性的限制,如:

 

  1. void fun(int a);  
  2. int fun(int a);  
  3. void fun(int& a);  
  4. void fun (int a int b=0);  

 

很可能引起C ++编译器的恐慌,它在遇到诸如fun(100)的调用时会十分不满。用户有义务保证任一调用形式不产生二义性。以下是一种常见的使用重载机制的例程:

  1. //test10.cpp  
  2. #include <graphics.h>  
  3. #include <iostream.h>  
  4. void Pixel(int x int y int color)  
  5. {  
  6. putpixel(x y color);  
  7. }  
  8. int Pixel(int x int y)  
  9. {  
  10. return getpixel(x y);  
  11. }  
  12. void main()  
  13. {  
  14. int Driver=VGA Mode=VGAHI;  
  15. initgraph(&Driver &Mode "");  
  16. Pixel(100 100 4);  
  17. int Color = Pixel(100 100);  
  18. closegraph();  
  19. cout << "Color of point(100 100):" << Color;  
  20. }  

可以想象C++将以上不同的Pixel()函数分别编码为Pixel_iii和Pixel_ii,它的形式包含了各入口参数的数据类型。注意,编码未包含返回值的信息,因而依赖于返回值类型的差异的函数重载是不稳定的。因此,连接器(linker)可以毫不费力地找到相应的模块。但这对于新旧C版本产生的模块连接恐怕添加了麻烦,因为传统的C函数库中并没有对函数名再作手脚的坏习惯,C++不得不提供关键字extern来保证这种连接的安全性,如下形式(注意‘C’可要大写):

  1. extern "C" 
  2. {  
  3. void Pixel(int x int y int Color);  
  4. };  

将告诉编译器只需要在函数库中找相应的Pixel模块,而不必自作聪明。而

  1. extern "C" 
  2. //' #include’一定要另起一行  
  3. #include "function. h"  
  4. };  

则声明包含在头文件function. h中所有函数模块皆采取C连接。

希望通过本文的介绍,能给你带来帮助。请继续看下一篇>>

【编辑推荐】

  1. C++新手之详细介绍MFC
  2. 举例介绍VC++中的ODBC编程
  3. 详细介绍C/C++时间函数使用方法
  4. C++基础学习之引用和指针
  5. 经验分享 C++编程技巧
责任编辑:于铁 来源: 互联网
相关推荐

2011-07-13 17:08:02

CC++

2011-07-13 17:42:32

CC++

2011-07-13 16:36:11

C++

2010-02-04 15:19:38

C++获取CPU信息

2021-12-06 23:00:36

CC++编程语言

2015-06-25 11:21:33

C++Objective-C

2011-06-15 15:29:25

Qt C++

2009-08-27 16:03:31

从c#到c++

2009-08-20 15:54:48

从C#到C++

2011-05-18 18:05:47

C#C++

2024-01-22 11:33:17

C++编程语言开发

2010-01-21 16:08:26

C++语言

2010-02-01 11:13:00

C++ Traits

2010-02-05 18:09:28

C++ Doxygen

2011-07-12 13:41:15

C++

2009-09-04 17:34:11

C#CC++

2010-01-28 16:58:32

学习C++感想

2010-02-06 13:47:08

C++标准扩展

2010-02-03 13:22:07

C++时间

2011-07-20 10:30:29

C语言
点赞
收藏

51CTO技术栈公众号