代码实现 C++ 程序从编写到最后得到运行结果,要经历以下一些步骤: 01、编写程序 用高级语言编写的程序,称为 "源程序" (source program)。源程序的后缀取决于 C++ 实现,下表列出了常用扩展名:
02、编译源程序 为使计算机能执行高级语言源程序,必须先用一种称为 “编译器 (complier)” 的软件 (也称:编译程序或编译系统),把源程序翻译成二进制形式的 “目标程序 (object program)。 编译是以源程序文件为单位分别编译的。目标程序一般以 .obj 或 .o 作后缀 (object 的缩写)。编译的作用,是对源程序进行词法检查和语法检查。 编译时,要对文件中的全部内容进行检查,编译结束后会显示所有编译出错信息。一般编译系统会给出的出错信息,分 2 种:一种是错误 (error)、一种是警告 (warning) 。 03、连接目标文件 改正所有错误并全部通过编译后,会得到一个或多个目标文件。 此时,要用系统提供的 “连接程序 (linker)” 将一个程序的所有目标程序、系统库文件及系统提供的其他信息连接起来,最终形成一个可执行的二进制文件,其后缀可直接执行的 .exe。 04、运行程序 运行最终形成的 .exe 可执行二进制文件,得到运行结果。 若运行结果不正确,应检查程序或算法是否有问题。 多泛型设计 根据 Effective C++ 第 3 版第一条的描述,C++ 由以下 4 个 "子语言" 组成: 01、C 子语言 C++ 支持 C 语言的几乎全部功能,主要是 C89 的部分,在语法上与 C 语言仅有极微妙的差别 (譬如:括号表达式的左右值性,具体请参考 C++ 标准文献)。 这部分功能对应于传统的面向过程的编程泛型,并提供了面向函数编程泛型的基础。 02、面向对象的 C++ 语言 C++ 语言原本不具备面向对象的设计功能,然而,随着面向对象编程概念的普及,C++ 语言也开发出了支持面向对象功能的版本。 这部分功能对应于面向对象的编程泛型。 03、泛型编程语言 C++ 的强大(但容易失控的)模板功能,使其能在编译期完成许多工作,大大提高了运行期效率,并大大提高了 C++ 的表达能力。 STL(C++标准模板库,Standard Template Library)是一个基于模板技术的库。随着 STL 的不断发展,其已逐渐成为 C++ 程序设计不可或缺的部分。STL 代码效率可能比一般的 native 代码低些,但其安全性与规范性使之大受欢迎。 STL 模板使 C++ 能够支持泛型编程(generic programming)和生成式编程(generative programming)的泛型。 04、Lambda C++ 11 标准引入的 Lambda,程序员可定义匿名函数,完善了 C++ 面向函数编程泛型的支持。
01、是和 C 语言同样高效且可移植的静态类型、多用途程序设计语言。 02、可直接、广泛支持多种程序设计风格(程序化程序设计、资料抽象化、面向对象程序设计、泛型程序设计)。 03、无需复杂的程序设计环境。 04、语言灵活、运算符数据结构丰富、具有结构化控制语句、程序执行效率高,且同时具有高级语言与汇编语言的优点;与其它语言相比 ,C++ 可直接访问物理地址,与汇编语言相比,又具有良好的可读性和可移植性。 05、尽量兼容 C 语言,并支持面向对象的方法。C++ 语言简洁、高效接近汇编语言,对 C 语言类型系统进行了改革性扩充;因此,C++ 比 C 语言更安全,C++ 编译系统能检查出更多的类型错误。另外,由于 C 语言的广泛使用,因而极大的促进了 C++ 的普及和推广。 06、虽与 C 语言的兼容使得 C++ 具有双重特点,但在概念上 C++ 完全与 C 语言不同,更面向对象。 07、为保证语言简洁和运行高效等,C++ 很多特性是以库(比如:STL)或其他形式提供的,并没有直接添加到语言本身里。 08、C++ 引入了面向对象的概念,使得开发人机交互类型的应用程序更为简单、快捷;很多优秀的程序框架,包括:Boost、Qt、MFC、OWL、wxWidgets、WTL 就是使用的 C++。 缺点 C++ 语言由于其本身的复杂性;因此,C++ 编译系统受复杂性影响,非常难于编写,即使能够使用的编译器如存在问题,也难于被发现。 由于本身的复杂性,复杂的 C++ 程序的正确性也相当难于保证。 数据是程序要处理的对象,数据可依其本身的特点进行分类。我们知道:数学中有整数、实数的概念,日常生活中需要用字符串来表示人的姓名和地址,有些问题的回答只能是 “是” 或 “否”(即逻辑 “真” 或 “假”)。不同类型的数据有不同的处理方法,譬如:整数和实数可以参加算术运算,但实数的表示又不同于整数,要保留一定的小数位;字符串可以拼接;逻辑数据可以参加 “与”、“或”、“非” 等逻辑运算。 编写计算机程序,目的就是为了解决客观世界中的现实问题。所以,高级语言也为我们提供了丰富的数据类型和运算。C++ 中的数据类型,分为:基本类型和自定义类型。基本类型是 C++ 编译系统内置的。 基本类型 C++ 的基本数据类型,如下表所示(下表中列出的各类型的长度和取值范围,是指以面向 80x86 处理器的 Viusal C++ 2012 和 gcc 4.8.1 的长度,其它的编译器并不一定是这个长度)。
类型转换 C++ 丰富的数据类型允许根据需要选择不同的类型,这也使得计算机的操作更复杂。 01、自动类型转换(隐式类型转换) 以下 4 种情况,计算机会自动进行类型转换: 在混合类型的算术表达式中 intival=3; doubledval=3.1415 ival+dval; // ival 被提升为 double 类型:3.0 用另外一种类型的表达式赋值 int*pi=NULL; // NULL(0) 被转换成了 int* 类型的空指针值 用一个表达式传递给一个函数调用 externdoublesqrt(double); sqrt(2); // 2 被提升为 double 类型:2.0 从一个函数返回一个表达式 doubledifference(intival1,intival2) { returnival1-ival2; // 返回值被提升为 double 类型。} 02、强制类型转换(显示类型转换) C++ 显式转换包含以下 4 种情况: static_cast 用法:static_cast < type-id > ( expression ) 说明:该运算符能把 expression 转换为 type-id 类型,但没有运行时,以类型检查来保证转换的安全性。 dynamic_cast 用法:dynamic_cast < type-id > (expression) 说明:该运算符能把expression 转换成 type-id 类型对象。Type-id 必须是类指针、类引用或 void*。 const_cast 用法:const_cast<type_id> (expression) 说明:该运算符可用来修改类型的const 或 volatile 属性。除了 const 或 volatile 修饰之外, type_id 和 expression 的类型是一样的。 reinterpret_cast 用法:reinterpret_cast<type-id> (expression) 说明:type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可把一个指针转换成一个整数,也可把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型指针,还可得到原先指针值)。 编程技巧 01、new 和 delete 运算符 new 和 delete 提供了存储的动态内存分配和释放功能,其的作用相当于 C 语言的函数 malloc() 和 free(),但性能更为优越。使用 new 较之使用 malloc() 有以下优点: 1)new 会自动计算要分配类型的大小,不使用 sizeof 运算符,比较省事,可避免错误。 2)自动返回正确的指针类型,不用进行强制指针类型转换。 3)可以用 new 对分配的对象进行初始化。 02、inline 对于频繁使用的函数,C 语言建议使用宏调用,代替函数调用以加快代码执行,减少调用开销。但是宏调用有许多弊端,可能引起不期望的副作用。譬如,宏:#define abs(a)(a)<0?(-a)a)),当使用 abs(i++) 时,这个宏就会出错。 所以在 C++ 中应使用 inline 内联函数替代宏调用,这样既可达到宏调用目的,又避免了宏调用的弊端。使用内联函数只须把 inline 关键字放在函数返回类型的前面。 03、函数重载 在 C 语言中,两个函数的名称不能相同,否则会导致编译错误。 而在 C++ 中,函数名称相同而参数数据类型不同或参数个数不同或二者皆不同的两个函数会被解释为重载。使用函数重载可帮助程序员处理更多复杂问题,避免使用诸如:intabs()、fabs()、dabs() 等繁杂的函数名称; 同时在大型程序中,使函数名易于管理和使用,而不必绞尽脑汁地去处理函数名。但必须注意,参数数据类型相同,但是函数返回类型不同的两个函数不能重载。 04、参数传递 在 C 语言中,如一个函数需要修改用作参数的变量值时 ,参数应声明为指针类型;当参数大小超过一个字长时,通过传值方式来传递参数的效率会较低,也需要用指针。 由于 C 语言的指针可以进行 p++,--p,p+=1 等算术运算,所以,编译器在编译时无法确定指针引用的变量。对于复杂程序,使用指针容易出错,程序也难以读懂。 C++ 可使用引用来代替指针,使程序更加清晰易懂。引用就是对变量取的一个别名,操作引用,相当于对原有变量进行操作。 05、指针与引用 指针与引用看上去完全不同(指针使用操作符 “*” 和 “->”,引用使用操作符 “&”),但它们似乎有相同的功能。指针与引用都是间接引用其他对象。如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下,都不能使用指向空值的引用。一个引用,必须总是指向某些对象。 因此,如使用一个变量并让它指向一个对象,但该变量在某些时候也可能不指向任何对象,这时应把变量声明为指针;因为,这样可赋空值给该变量。相反,如变量肯定指向一个对象,譬如:设计不允许变量为空,这时就可以把变量声明为引用。 06、缺省参数 C++中的函数,可以使用缺省参数。 通常情况下,一个函数应具有尽可能大的灵活性。使用缺省参数为程序员处理更复杂、更灵活问题提供了有效的解决方法;所以,C++ 代码会大量地使用缺省参数。 需要说明的是:所有缺省参数,必须出现在不缺省参数的右边。亦即:一旦开始定义缺省参数,就不可再说明非缺省参数。否则,当省略其中一个参数时,编译器无法知道是自定义了这个参数,还是利用了缺省参数而定义了非缺省的参数。 07、使用 STL STL(Standard Template Library,标准模板库)代码从广义上讲,分 3 类:algorithm(算法)、container(容器)及 iterator(迭代器),还包括一些工具类,如 auto_ptr。 所有代码采用模板类和模板函数的方式,相较传统由函数和类组成的库而言,提供了更好的代码重用机会。 作用符被重载,可像访问数组一样访问 vector 中的元素。 08、使用模板 模板是 C++ 的特性,是函数和类能作用于不同类型,而不需要针对每一个具体类型重复相同代码。 与模板相反的重载 (Overloading),对重载函数而言,C++ 检查机制可通过函数参数的不同及所属类的不同,正确调用重载函数。譬如:求两个数的最大值,定义 MAX() 函数需对不同的数据类型分别定义不同重载 (Overload) 版本。若使用模板可只写一个通用 MAX 模板,不需要针对每个类型重复相同的逻辑。 |