C++ - C 语言之增强编译型 面向对象的跨平台高级编程语言
C++ 是在 C 语言基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式 ── 面向对象编程、泛型编程和过程化编程。C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言。
C++ 支持类:类、封装、重载等特性!C++ 编程领域众广,常用于系统开发,引擎开发等应用领域,是至今为止最受广大程序员受用的最强大编程语言之一。
1983 年 C++ 这个名字由 Rick Mascitti 于提出建议,于1983 年 12 月首次使用。1983 年之前,尚处于研究阶段曾被称为 “new C”,之后改为 “C with Class”。在计算机科学中,C++ 仍被称为 C 语言的上层结构。它最后得名于 C 语言中的 “++” 操作符(其对变量的值进行递增)。在共同的命名约定中,使用 “+” 以表示增强的程序。Stroustrup 说:“这个名字象征着源自于 C 语言变化的自然演进”。
1992 年 Rick Mascitti 在被非正式地问起名字的由来时,他表示这是在半开玩笑中说出的。他从没想过 C++ 会成为这门语言的正式名字。有一个关于 C++ 名字的笑话,当你使用后缀 ++ 时,赋值发生在加运算之后(因此,它应该是 ++C,而不是 C++,这个笑话是说时下某些程序员还在以使用 C 的方式使用 C++,这通常被一些权威著作认为是不正确的)。
注意:C+ 是一个和 C/C++ 无关的早期编程语言。
计算机诞生初期,人们要使用计算机必须用机器语言或汇编语言编写程序。世界上第一种计算机高级语言是诞生于 1954 年的 FORTRAN 语言。之后出现了多种计算机高级语言,其中使用最广泛、影响最大的当推 BASIC 语言和 C 语言。
10 倍以上效率提升 智能GUI文档翻译 Python Qt/C++ HTML5 网站站群 "数字 IDE 专业版" 开发工具 http://idepro.digitser.cn/ http://forum.digitser.cn/thread-2184-1-1.html
百度网盘 https://pan.baidu.com/s/1jIzOgzs
软件仓库 https://github.com/digitser https://digitser.sourceforge.io/ https://pan.baidu.com/s/1TV70__Be1ta0ney1-tudFQ
BASIC 语言是1964 年由 Dartmouth 学院 John G. Kemeny 与 Thomas E. Kurtz 两位教授在 FORTRAN 语言的基础上简化而成的,适用于初学者设计的小型高级语言;C 语言是 1972 年由美国贝尔实验室的 Dennis M. Ritchie 所开发,采用结构化编程方法,遵从自顶向下的原则。在操作系统和系统使用程序及需要对硬件进行操作的场合,用 C 语言明显优于其它高级语言,但在编写大型程序时,C 语言仍面临着挑战。
1983 年贝尔实验室的 Bjarne Stroustrup 在 C 语言基础上推出了 C++。
在 “C with Class” 阶段,研制者在 C 语言的基础上加进去的特征主要有:类及派生类、共有和私有成员的区分、类的构造函数和析构函数、友元、内联函数、赋值运算符的重载等。
1985 年公布的 C++ 语言 1.0 版的内容中,又添加了一些重要特征:虚函数的概念、函数和运算符重载、引用、常量(constant)等。
1989 年推出的 2.0 版形成了更加完善的,支持面向对象程序设计的 C++ 语言,新增加的内容包括:类保护成员、多重继承、对象初始化与赋值递归机制、抽象类、静态成员函数、const 成员函数等。
1993 年的 C++ 语言 3.0 版本是 C++ 语言的进一步完善,其中最重要的新特征是:模板(template);此外,还解决了多重继承产生的二义性问题及对构造函数与析构函数的处理等。
1998 年 C++ 标准(ISO/IEC 14882 Standard for the C++ Programming Language)得到了国际标准化组织(ISO)和美国标准化协会(ANSI)的批准,标准 C++ 语言及其标准库更体现了 C++ 语言设计的初衷。名字空间的概念、标准模板库(STL)中增加的标准容器类、通用算法类和字符串类型等使得 C++ 语言更为实用。此后 C++ 是具有国际标准的编程语言,该标准通常简称 ANSI C++ 或 ISO C++ 98 标准,以后每 5 年视实际需要更新一次标准。
2003 年通过了 C++ 标准第二版(ISO/IEC 14882:2003):这个新版本是一次技术性修订,对第一版进行了整理 —— 修订错误、减少多义性等,但没有改变语言特性。这个版本常被称为 C++ 03。
此后,新标准草案叫做 C++ 0x。对于 C++ 0x 标准草案的最终国际投票已于 2011 年 8 月 10 日结束,且所有国家都投出了赞成票,C++ 0x 已毫无异议地成为正式国际标准。先前被临时命名为 C++ 0x 的新标准正式定名为 ISO/IEC 14882:2011,简称 ISO C++ 11 标准。C++ 11 标准将取代现行的 C++ 标准 C++ 98 和 C++ 03。
2011 年 09 月 01 日国际标准化组织出版发布《ISO/IEC 14882:2011》,名称是:Information technology -- Programming languages -- C++ Edition: 3,常被称为 C++ 11。
2014 年 08 月 18 日国际标准化组织出版发布《ISO/IEC 14882:2014》,名称是:Information technology -- Programming languages -- C++ Edition: 4,常被称为 C++ 14。
C 语言是 C++ 的基础,C++ 和 C 语言在很多方面是兼容的。C 语言是一种结构化语言,它的重点在于算法与数据结构。C 程序的设计首要考虑的是:如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 过程/事物 控制)。C++ 程序首要考虑的是:如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可通过获取对象的状态信息,得到输出或实现 过程/事物 控制。
所以,C 语言和 C++ 的最大区别在于:它们解决问题的思想方法是不一样的。
C++ 对 C 的 “增强” 表现在 6 方面:
01、类型检查更为严格;
02、增加了面向对象的机制;
03、增加了泛型编程的机制(Template);
04、增加了异常处理;
05、增加了运算符重载;
06、增加了标准模板库(STL)。
C++ 一般被认为是 C 语言的超集(Superset),但这并不严谨。大部分的 C 语言代码可轻易在 C++ 中正确编译,但仍有少数差异,导致某些有效 C 语言代码在 C++ 中失效,或者在 C++ 中有不同的行为。最常见的差异之一是,C 语言允许从 void* 隐式转换到其它的指针类型,但 C++ 不允许。以下是有效 C 语言代码:
- //从 void*
- 类型隐式转换为 int*
- 类型
- int*i=malloc(sizeof(int)*5);
复制代码
要使以上代码,在 C 语言和 C++ 两者间皆可运作,就需要使用以下显式转换:
- int*i=(int*)malloc(sizeof(int)*5);
复制代码
另一个常见可移植问题是:C++ 定义了新关键字,譬如:new、class,它们在 C 语言程序中是可作为识别字(比如:变量名)的。
C 语言标准 C99 去除了一些不兼容处,支持了一些 C++ 特性,譬如:// 注解、及在代码中混合声明。不过,C 语言标准 C99 也纳入几个和 C++ 冲突的新特性(比如:可变长度数组、原生复数类型和复合逐字常数)。
若要混用 C 语言和 C++ 的代码,则所有在 C++ 中调用的 C 代码,必须放在 extern "C" { /* C 代码 */ } 内。
争议
“在这 12 年里,C++ 用户人数大约每 7 个月半增加一倍”,是许多 C++ 相关文件必引的一段话;然而,时至今日新语言层出不穷,用户人数已不太可能以如此速度增长。
分析机构 EvansData 定期对开发人员展开调查,其数据显示,以 C++ 为工具的开发人员在整个开发界所占的比例由 1998 年春天的 76% 下降至 2004 年秋的 46%。
Forrester 最新调查显示,C++、微软 Visual Basic 和 Java 是众多公司产品体系的首选语言。对 100 家公司的调查显示,C/C++、Visual Basic 和 Java 在产品体系中的使用比例分别是 59%、61% 和 66%。
一部分 Unix/C 程序员对 C++ 语言深恶痛绝,他们批评的理由如下: 01、STL 以非常丑陋的方式封装了各种数据结构和算法,写出来的代码难以理解、不美观;
02、C++ 编译器复杂和不可靠,不适合构建人命关天类型的程序;
03、一部分人认为面向对象技术徒增学习成本,不如面向过程的 C 语言简单容易使用,尤其是在系统软件的构建上。
概括说来,UNIX 程序员批评 C++ 主要是由于 UNIX 社区与 C++ 社区的文化差异。一个值得注意的事情,是 Linux 之父 Linus Torvalds 曾经炮轰 C++;图灵奖得主尼克劳斯·维尔特也曾经批评 C++ 语言太复杂、语法语义模糊,是 “拙劣工程学” 的成果。
事实上,对于 C++ 语言的批评并不只来源于 Unix/Unix-Like 系统下的程序员。就像 C++ 语言本身是一个跨平台的语言一样,对 C++ 的批评并不局限于 Unix/Unix-Like 系统用户。
一个确定的观点是:C++ 是一门复杂的语言、这门语言拥有过多的特性从而难以彻底掌握;C++ 的某些库难以学习、掌握并应用于实际当中;很多程序员都认为 C++ 是一个过度设计的程序语言。
代码实现
C++ 程序从编写到最后得到运行结果,要经历以下一些步骤:
01、编写程序 用高级语言编写的程序,称为 "源程序" (source program)。源程序的后缀取决于 C++ 实现,下表列出了常用扩展名:
# | C++ 实现 | 源程序扩展名 | 备注 | 01 | Unix | C, cc, cxx, c |
| 02 | GNU C++ | C, cc, cxx, cpp, c++ |
| 03 | Digital Mars | cpp, cxx |
| 04 | Borland | C++ cpp |
| 05 | Watcom | cpp |
| 06 | Microsoft Visual C++ | cpp, cxx, cc |
| 07 | Metrowerks CodeWarrior | cpp, cp, cc, cxx, 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 的长度,其它的编译器并不一定是这个长度)。
# | 类型名 | 长度(字节) | 取值范围 | 备注 | 01 | bool | 1 | false,true |
| 02 | char
| 1 | -128~127 |
| 03 | signed char | 1
| -128~127 |
| 04 | unsigned char | 1 | 0~255 |
| 05 | short (signed short) | 2 | -32768~32767 |
| 06 | unsigned short | 2 | 0~65535 |
| 07 | int (signed int) | 4 | -2147483648~2147483647 |
| 08 | unsigned int | 4 | 0~4294967295 |
| 09 | long (signed long) | 4 | -2147483648~2147483647 |
| 10 | unsigned long | 4 | 0~4294967295 |
| 11 | long long (signed long long) | 8 | -9223372036854775807~9223372036854775807 |
| 12 | unsigned long long | 8 | 0~18446744073709551615 |
| 13 | float | 4 |
|
| 14 | double | 8 |
|
| 15 | long double | 8 |
|
|
类型转换
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 模板,不需要针对每个类型重复相同的逻辑。
类和对象
类是具有相同属性、相同方法的对象集合,类是一种既包含数据又包含函数的抽象数据类型。
对象是类进行实体化后的产物,是一个实体。
C++ 先声明一个类类型,然后再用它去定义若干个同类型的对象。对象就是类类型的一个变量。可以这样说,类是对象模板,是用来定义对象的一种抽象类型。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
01、声明类类型 类是用户自己指定的类型。如程序中要用到类类型,必须根据需要进行声明,或使用别人已设计好的类。C++ 标准本身并不提供现成的类名称、结构、内容。
C++ 声明一个类的类型和声明一个结构体类型是相似的。以下代码为声明一个结构体类型方法:
- struct Student // 声明一个名为 Student 的结构体
- 类型
- {
- int num;
- char name[20];
- char sex;
- };
- Student stud1,stud2; // 定义两个结构体变量 stud1 和 stud2,只包括数据,没有包括操作
复制代码
以下代码为声明一个类:
- class Student // 以 class 开头
- {
- int num;
- char name[20];
- char sex; // 以上 3 行是数据成员
- void display() // 这是成员函数
- {
- cout<<″num:″<<num<<endl;
- cout<<″name:″<<name<<endl;
- cout<<″sex:″<<sex<<endl;
- }; // 以上 4 行是函数中的操作语句
-
- };
- Student stud,stud1; // 定义两个对象 stud 和 stud1
复制代码
事实上,也可以用 struct 关键字声明一个类。这样的类,所有成员默认权限都是 public (除非特别写上权限);而用 class 声明的类,所有成员的默认权限都是 private。
可以看到声明类的方法,是由声明结构体类型的方法发展而来,类就是对象类型。实际上,类是一种广义的数据类型。类这种数据类型中的数据既包含数据,也包含操作数据的函数。
不能把类中的全部成员与外界隔离,一般是把数据隐蔽起来,而把成员函数作为对外界的接口。可以将上面类的声明改为
- class Student // 以 class 开头
- {
- private: // 声明私有成员
- intnum;
- char name[20];
- char sex;
- public: // 声明公共成员
- void display()
- {
- cout<<″num:″<<num<<endl;
- cout<<″name:″<<name<<endl;
- cout<<″sex:″<<sex<<endl;
- }
- };
- Student stud1,stud2;//定义两个对象 stud1 和 stud2
复制代码
如在类定义中既不指定 private,也不指定 public,则系统就默认为是私有的。归纳以上对类类型的声明,可得到其一般形式如下:
- class
- 类名
- {
- private:
- // 私有的数据和成员函数;
- public:
- // 公用的数据和成员函数;
- };
复制代码
private 和 public 称为成员访问限定符 (member access specifier)。除 private 和 public 外,还有一种成员访问限定符 protected (受保护的);用 protected 声明的成员称为受保护成员,其不能被类外访问 (这点与私有成员类似),但可被派生类成员函数访问。
在声明类类型时,声明为 private 的成员和声明为 public 的成员的次序任意,既可以先出现 private 部分,也可以先出现 public 部分。
在一个类中,关键字 private 和 public 可以分别出现多次。每个部分的有效范围,是到出现另一个访问限定符或类体结束时 (最后一个右花括号) 为止。为使程序清晰,应养成这样的习惯: 使每一个成员访问类定义体中的限定符只出现一次。
C++ 程序多数先写 public 部分,把 private 部分放在类体的后部。这样可以使用户将注意力集中在能被外界调用的成员上,使阅读者的思路更清晰一些。
在 C++ 程序中,经常可以看到类。为方便起见,常用 C++ 编译系统往往会向用户提供类库 (但不属于 C++ 语言组成部分),内装常用基本类,供用户使用。不少用户也把自己或本单位经常用到的类放在一个专门类库中,需要用到时可直接调用,这样就减少了程序设计的工作量。
02、定义对象 上述程序段中,最后一行用已声明的 Student 类来定义对象,这种方法很容易理解。经过定义后,stud1 和 stud2 就成为了具有 Student 类特征的对象。stud1 和 stud2 这 2 个对象分别包括 Student 类中定义的数据和函数。
定义对象也可使用以下几种方法:
先声明类类型,然后再定义对象 前面用的就是这种方法,如 Student stud1,stud2; // Student 是已经声明的类类型;C++ 声明类类型后,定义对象有两种形式。
1)class 类名 对象名 如: class Student stud1,stud2;
把 class 和 Student 结合起来作为一个类名,用来定义对象。
2)类名 对象名 如: Student stud1,stud2;
直接用类名定义对象。
这两种方法是等效的。第 1 种方法是从 C语言继承下来的,第 2 种方法是 C++ 的特色,显然第 2 种方法更为简捷方便。
在声明类类型的同时定义对象 - class Student // 声明类类型
- {
- public: // 先声明公用部分
- void display()
- {
- cout<<″num:″<<num<<endl;
- cout<<″name:″<<name<<endl;
- cout<<″sex:″<<sex<<endl;
- }
- private: // 后声明私有部分
- int num;
- char name[20];
- char sex;
- }stud1,stud2; // 定义 stud1 和 stud2 两个 Student 类对象
复制代码
在定义 Student 类的同时,定义 stud1 和 stud2 两个 Student 类对象。
不出现类名,直接定义对象
- class // 无类名
- {
- private: // 声明以下部分为私有的
- //...
- public: // 声明以下部分为公用的
- //...
- }stud1,stud2; // 定义 stud1 和 stud2 两个无类名的类对象
复制代码
在 C++ 中直接定义对象是合法的、允许的,但却很少用,也不提倡用。在实际程序开发中,一般采用以上 3 种方法中的第 1 种方法。在小型程序中或所声明的类只用于本程序时,也可采用第 2 种方法。在定义一个对象时,编译系统会为这个对象分配存储空间,以存放对象中的成员。
类和结构体
C++ 增加了 class 类型后,仍保留了结构体类型 (struct ),且把它的功能也扩展了;C++ 允许用 struct 定义一个类型。可将前面用关键字 class 声明的类类型,改为用关键字 struct:
- struct Student // 用关键字 struct 来声明一个类类型
- {
- private: // 声明以下部分为私有的
- int num; // 以下 3 行为数据成员
- char name[20];
- char sex;
- public: // 声明以下部分为公用的
- void display() //成员函数
- {
- cout<<″num:″<<num<<endl;
- cout<<″name:″<<name<<endl;
- cout<<″sex:″<<sex<<endl;
- }
- };
- Student stud1,stud2;//定义 stud1 和stud2 两个 Student 类对象
复制代码
为使结构体类型也具有封装特征,C++ 不是简单地继承 C 语言结构体,而是使其具有类的特点,以便于面向对象程序设计。用 struct 声明的结构体类型实际上也就是类。用 struct 声明的类,如果对其成员不作 private 或 public 的声明,系统将默认为 public。
如果想分别指定私有成员和公用成员,则应使用 private 或 public 作显式声明。
而用 class 定义的类,如果不作 private 或 public 声明,系统将其成员默认为 private,在需要时也可以用显式声明改变。如希望成员是公用的,使用 struct 比较方便,如希望部分成员是私有的,宜用 class。
建议尽量使用 class 来建立类,写出完全体现 C++ 风格的程序。
关键字
关键字 keyword 是 C++ 语言保留的标识符,每个关键字都有特殊含义。经过预处理后,关键字从预处理记号 (preprocessing-token) 中区出来,剩下的标识符作为记号 (token),用于声明对象、函数、类型、命名空间等。不能声明与关键字同名的标识符。
各个版本的 ISO C++ 都规定以下划线接大写字母起始的标识符保留给实现。编译器可用这些保留标识符作为扩展关键字,这不保证可移植性。ISO C++ 98 关键字共63 个,此处严格按标准原文排版:
asm
| do
| if
| return
| typedef
| auto
| double
| inline
| short
| typeid
| bool
| dynamic_cast
| int
| signed
| typename
| break
| else
| long
| sizeof
| union
| case
| enum
| mutable
| static
| unsigned
| catch
| explicit
| namespace
| static_cast
| using
| char
| export
| new
| struct
| virtual
| class
| extern
| operator
| switch
| void
| const
| false
| private
| template
| volatile
| const_cast
| float
| protected
| this
| wchar_t
| continue
| for
| public
| throw
| while
| default
| friend
| register
| true
|
| delete
| goto
| reinterpret_cast
| try
| |
常见错误
# | 英文 | 参考译文 | 备注 | 001
| Ambiguous operators need parentheses
| 模棱两可的操作符需要括号
|
| 002
| Ambiguous symbol ''xxx''
| 不明确的符号
|
| 003
| Argument list syntax error
| 参数表语法错误
|
| 004
| Array bounds missing
| 数组界限符丢失
|
| 005
| Array size toolarge
| 数组尺寸太大
|
| 006
| Bad character in paramenters
| 参数中有不适当的字符
|
| 007
| Bad file name format in include directive
| 包含命令中文件名格式不正确
|
| 008
| Bad ifdef directive synatax
| 编译预处理ifdef有语法错
|
| 009
| Bad undef directive syntax
| 编译预处理undef有语法错
|
| 010
| Bit field too large
| 位字段太长
|
| 011
| Call of non-function
| 调用未定义的函数
|
| 012
| Call to function with no prototype
| 调用函数时没有函数的说明
|
| 013
| Cannot modify a const object
| 不允许修改常量对象
|
| 014
| Case outside of switch
| 漏掉了case 语句
|
| 015
| Case syntax error
| Case 语法错误
|
| 016
| Code has no effect
| 代码不可能被执行到
|
| 017
| Compound statement missing{
| 分程序漏掉"{"
|
| 018
| Conflicting type modifiers
| 互相冲突的类型说明符设置
|
| 019
| Constant expression required
| 需要常量表达式
|
| 020
| Constant out of range in comparison
| 在比较中常量超出范围
|
| 021
| Conversion may lose significant digits
| 转换时会丢失数值的精度
|
| 022 | Conversion of near pointer not allowed
| 不允许转换近指针
|
| 023
| Could not find file ''xxx''
| 找不到XXX文件
|
| 024
| Declaration missing ;
| 声明中缺少";"
|
| 025
| Declaration syntax error
| 声明中出现语法错误
|
| 026
| Default outside of switch
| Default 出现在switch语句之外
|
| 027
| Define directive needs an identifier
| 定义编译预处理需要标识符
|
| 028
| Division by zero
| 用零作除数
|
| 029
| Do statement must have while
| Do-while语句中缺少while部分
|
| 030
| Enum syntax error
| 枚举类型语法错误
|
| 031
| Enumeration constant syntax error
| 枚举常数语法错误
|
| 032
| Error directive :xxx
| 错误的编译预处理命令
|
| 033
| Error writing output file
| 写输出文件错误
|
| 034
| Expression syntax error
| 表达式语法错误
|
| 035
| Extra parameter in call
| 调用时出现多余错误
|
| 036
| File name too long
| 文件名太长
|
| 037
| Function call missing
| 函数调用缺少右括号
|
| 038
| Fuction definition out of place
| 函数定义位置错误
|
| 039
| Fuction should return a value
| 函数必需返回一个值
|
| 040
| Goto statement missing label
| Goto语句没有标号
|
| 041
| Hexadecimal or octal constant too large
| 16进制或8进制常数太大
|
| 042
| Illegal character ''x''
| 非法字符x
|
| 043
| Illegal initialization
| 非法的初始化
|
| 044
| Illegal octal digit
| 非法的8进制数字
|
| 045
| Illegal pointer subtraction
| 非法的指针相减
|
| 046
| Illegal structure operation
| 非法的结构体操作
|
| 047
| Illegal use of floating point
| 非法的浮点运算
|
| 048
| Illegal use of pointer
| 指针使用非法
|
| 049
| Improper use of a typedefsymbol
| 类型定义符号使用不恰当
|
| 050
| In-line assembly not allowed
| 不允许使用行间汇编
|
| 051
| Incompatible storage class
| 存储类别不相容
|
| 052
| Incompatible type conversion
| 不相容的类型转换
|
| 053
| Incorrect number format
| 错误的数据格式
|
| 054
| Incorrect use of default
| Default使用不当
|
| 055
| Invalid indirection
| 无效的间接运算
|
| 056
| Invalid pointer addition
| 指针相加无效
|
| 057
| Irreducible expression tree
| 无法执行的表达式运算
|
| 058
| Lvalue required
| 需要逻辑值0或非0值
|
| 059
| Macro argument syntax error
| 宏参数语法错误
|
| 060
| Macro expansion too long
| 宏的扩展以后太长
|
| 061
| Mismatched number of parameters in definition
| 定义中参数个数不匹配
|
| 062
| Misplaced break
| 此处不应出现break语句
|
| 063
| Misplaced continue
| 此处不应出现continue语句
|
| 064
| Misplaced decimal point
| 此处不应出现小数点
|
| 065
| Misplaced elif directive
| 不应编译预处理elif
|
| 066
| Misplaced else
| 此处不应出现else
|
| 067
| Misplaced else directive
| 此处不应出现编译预处理else
|
| 068
| Misplaced endif directive
| 此处不应出现编译预处理endif
|
| 069
| Must be addressable
| 必须是可以编址的
|
| 070
| Must take address of memory location
| 必须存储定位的地址
|
| 071
| No declaration for function ''xxx''
| 没有函数xxx的说明
|
| 072
| No stack
| 缺少堆栈
|
| 073
| No type information/没有类型信息
| 缺少堆栈
|
| 074
| Non-portable pointer assignment
| 不可移动的指针(地址常数)赋值
|
| 075
| Non-portable pointer comparison
| 不可移动的指针(地址常数)比较
|
| 076
| Non-portable pointer conversion
| 不可移动的指针(地址常数)转换
|
| 077
| Not a valid expression format type
| 不合法的表达式格式
|
| 078
| Not an allowed type
| 不允许使用的类型
|
| 079
| Numeric constant too large
| 数值常太大
|
| 080
| Out of memory
| 内存不够用
|
| 081
| Parameter ''xxx'' is never used
| 能数xxx没有用到
|
| 082
| Pointer required on left side of ->
| 符号->的左边必须是指针
|
| 083
| Possible use of ''xxx'' before definition
| 在定义之前就使用了xxx(警告)
|
| 084
| Possibly incorrect assignment
| 赋值可能不正确
|
| 085
| Redeclaration of ''xxx''
| 重复定义了xxx
|
| 086
| Redefinition of ''xxx'' is not identical
| xxx的两次定义不一致
|
| 087
| Register allocation failure
| 寄存器定址失败
|
| 088
| Repeat count needs an lvalue
| 重复计数需要逻辑值
|
| 089
| Size of structure or array not known
| 结构体或数给大小不确定
|
| 090
| Statement missing ;
| 语句后缺少";"
|
| 091
| Structure or union syntax error
| 结构体或联合体语法错误
|
| 092
| Structure size too large
| 结构体尺寸太大
|
| 093
| Sub scripting missing ]
| 下标缺少右方括号
|
| 094
| Superfluous & with function or array
| 函数或数组中有多余的"&"
|
| 095
| Suspicious pointer conversion
| 可疑的指针转换
|
| 096
| Symbol limit exceeded
| 符号超限
|
| 097
| Too few parameters in call
| 函数调用时的实参少于函数的参数不
|
| 098
| Too many default cases
| Default太多(switch语句中一个)
|
| 099
| Too many error or warning messages
| 错误或警告信息太多[13]
|
| 100
| Too many type in declaration
| 说明中类型太多
|
| 101
| Too much auto memory in function
| 函数用到的局部存储太多
|
| 102
| Too much global data defined in file
| 文件中全局数据太多
|
| 103
| Two consecutive dots
| 两个连续的句点
|
| 104
| Type mismatch in parameter xxx
| 参数xxx类型不匹配
|
| 105
| Type mismatch in redeclaration of ''xxx''
| xxx重定义的类型不匹配
|
| 106
| Unable to create output file ''xxx''
| 无法建立输出文件xxx
|
| 107
| Unable to open include file ''xxx''
| 无法打开被包含的文件xxx
|
| 108
| Unable to open input file ''xxx''
| 无法打开输入文件xxx
|
| 109
| Undefined label ''xxx''
| 没有定义的标号xxx
|
| 110
| Undefined structure ''xxx''
| 没有定义的结构xxx
|
| 111
| Undefined symbol ''xxx''
| 没有定义的符号xxx
|
| 112
| Unexpected end of file in comment started on line xxx
| 从xxx行开始的注解尚未结束文件不能结束
|
| 113
| Unexpected end of file in conditional started on line xxx
| 从xxx 开始的条件语句 尚未结束文件不能结束
|
| 114
| Unknown assemble instruction
| 未知的汇编结构
|
| 115
| Unknown option
| 未知的操作
|
| 116
| Unknown preprocessor directive: ''xxx''
| 不认识的预处理命令xxx
|
| 117
| Unreachable code
| 无路可达的代码
|
| 118
| Unterminated string or character constant
| 字符串缺少引号
|
| 119
| User break
| 用户强行中断了程序
|
| 120
| Void functions may not return a value
| Void类型的函数不应有返回值
|
| 121
| Wrong number of arguments
| 调用函数的参数数目错
|
| 122
| ''xxx'' not an argument
| xxx不是参数
|
| 123
| ''xxx'' not part of structure
| xxx不是结构体的一部分
|
| 124
| xxx statement missing (
| xxx语句缺少左括号
|
| 125
| xxx statement missing )
| xxx语句缺少右括号
|
| 126
| xxx statement missing ;
| xxx缺少分号
|
| 127
| xxx'' declared but never used
| 说明了xxx但没有使用
|
| 128
| xxx'' is assigned a value which is never used
| 给xxx赋了值但未用过
|
| 129
| Zero length structure
| 结构体的长度为零
|
|
版本历史
时间 | 版本 | 事件 | 备注 | 1998 年 | C++ 98 | C++ 标准第一版,正式名称为 ISO/IEC 14882:1998 | 绝大多数编译器都支持 C++98 标准
不过当时错误地引入了 export 关键字
由于技术上的实现难度,除了 Comeau C++ 编译器 export 关键字以外,没有任何编译器支持 export 关键字
并且这个标准对现代一些编译理念有相当的差距,有很多在高级语言都应当有的功能,它都没有
这也正是后来需要制定 C++11 标准的原因所在 | 2003 年 | C++ 03 | C++ 标准第二版,正式名称为 ISO/IEC 14882:2003 | 这是 C++ 98 的修订版,与 C++ 98 几乎一样,没做什么修改
仅是对 C++ 98 做了一些 "勘误"
连主流编译器 (受 C99 标准影响) 都已支持的 long long 都没有被加入 C++ 03 标准
| 2011年 | C++ 11 | C++ 标准第三版,正式名称为 ISO/IEC 14882:2011 | C++ 11 标准为 C++ 98 发布后 13 年来第一次重大修正
C++ 11 包含核心语言新机能,拓展了 C++ 标准程序库
加入了大部分的 C++ Technical Report 1 程序库 (数学上的特殊函数除外)
| 2014年 | C++ 14 | C++ 标准第四版,正式名称为 ISO/IEC 14882:2014
正式名为 International Standard ISO/IEC 14882:2014(E) Programming Language C++
| C++ 14 是 C++ 11 的增量更新
C++ 14 旨在作为 C++ 11 的一个小扩展,主要提供漏洞修复和小改进
C++ 14 作者 Bjarne Stroustrup 称,主要的编译器开发商已实现了 C++ 14 规格
主要是支持普通函数的返回类型推演、泛型 lambda、扩展的 lambda 捕获、
对 constexpr 函数限制的修订、constexpr 变量模板化等等
| | | | | | | | |
"长按二维码" 或 "扫一扫" 关注 "德云社区" 微信公众号
版权声明:
本文为独家原创稿件,版权归 德云社区,未经许可不得转载;否则,将追究其法律责任。
|