-
c++
C++是在 的基础上开发的一种面向对象编程语言,应用广泛;C++支持多种编程范式 -- 、 和过程化编程。最新正式标准C++于2014年8月18日公布。 [1] 其编程领域众广,常用于系统开发,引擎开发等应用领域,是至今为止最受广大程序员受用的最强大编程语言之一,支持类:类、封装、重载等特性!
- 中文名
- C++语言 外文名
- The C++ Programming Language 类 别
- 计算机程序设计语言
- 创始人
- Bjarne Stroustrup 创始公司
- 贝尔实验室 基本内容
- 类、封装、重载、继承、模版
目录
- 1
- ▪
- ▪
- ▪
- ▪
- 2
- ▪
- ▪
- 3
- ▪
- ▪
- ▪
- 4
- ▪
- ▪
- ▪
- ▪
- ▪
- ▪
- ▪
- 5
- ▪
- ▪
- 6
- 7
- 8
- ▪
- ▪
- ▪
- 9
- 10
- ▪
- ▪
- ▪
- 11
- 12
- 13
- ▪
- ▪
- ▪
- ▪
从C到C++
c++代码
计算机诞生初期,人们要使用计算机必须用 或 编写程序。世界上第一种计算机高级语言是诞生于1954年的 。之后出现了多种计算机 ,其中使用最广泛、影响最大的当推 和 。 是 1964年由 Dartmouth 学院 John G. Kemeny 与 Thomas E. Kurtz 两位教授在FORTRAN语言的基础上简化而成的, 适用于初学者设计的小型高级语言;C语言是1972年由美国贝尔实验室的D.M.Ritchie所开发,采用 方法,遵从 的原则。 [2] 在操作系统和系统使用程序以及需要对硬件进行操作的场合,用C语言明显优于其它高级语言,但在编写大型程序时,C语言仍面临着挑战。
1983年, 的 在C语言基础上推出了C++ [1] 。 C++进一步扩充和完善了C语言,是一种 的程序设计语言。
名称由来
C++这个名字是Rick Mascitti于1983年中所建议的,并于1983年12月首次使用。更早以前,尚在研究阶段的发展中语言曾被称为“new C”,之后是“C with Class” [3] 。在计算机科学中,C++仍被称为C语言的上层结构。它最后得名于C语言中的“++”操作符(其对变量的值进行递增)。而且在共同的命名约定中,使用“+”以表示增强的程序。Stroustrup说:“这个名字象征着源自于C语言变化的自然演进”。
注:C+是一个和C/C++无关的早期编程语言。
Rick Mascitti在1992年被非正式地问起名字的由来,他表示这是在半开玩笑中说出的。他从没想过C++会成为这门语言的正式名字。有一个关于C++名 字的笑话,当你使用后缀++时,赋值发生在加运算之后(因此,它应该是++C,而不是C++,这个笑话是说时下某些程序员还在以使用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/IEC14882 Standard for the C++ Programming Language)得到了 (ISO)和美国标准化协会( )的批准,标准C++语言及其标准库更体现了C++语言设计的初衷。 的概念、 (STL)中增加的标准容器类、通用算法类和字符串类型等使得C++语言更为实用。此后C++是具有国际标准的编程语言,该标准通常简称ANSI C++或ISO C++ 98标准,以后每5年视实际需要更新一次标准。
后来又在2003年通过了C++标准第二版(ISO/IEC 14882:2003):这个新版本是一次技术性修订,对第一版进行了整理——修订错误、减少多义性等,但没有改变语言特性。这个版本常被称为C++03。 [2]
此后,新的标准草案叫做C++ 0x。对于C++ 0x标准草案的最终国际投票已于2011年8月10日结束,并且所有国家都投出了赞成票, 已 经毫无异议地成为正式国际标准。先前被临时命名为C++0x的新标准正式定名为ISO/IEC 14882:2011,简称ISO C++ 11标准。C++ 11标准将取代现行的C++标准C++98和C++03。国际标准化组织于2011年9月1日出版发布《ISO/IEC 14882:2011》,名称是:Information technology -- Programming languages -- C++ Edition: 3。 [4-6]
与C的关系
C语言是C++的基础,C++和C语言在很多方面是兼容的。
C语言是一个结构化语言,它的重点在于算法与数据结构。C程序的设计首要 考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事物)控制)。C++,首要考虑的是如何构造一个对象模型,让这个模 型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事物)控制。所以C语言和C++的最大区别在于它们解决问题的思想方 法不一样。
C++对C的“增强”,表现在六个方面:
(1) 类型检查更为严格。
(2) 增加了面向对象的机制。
(3) 增加了泛型编程的机制(Template)。
(4) 增加了异常处理。
(5) 增加了运算符重载。
(6) 增加了标准模板库(STL)。
与C不兼容之处
C++一般被认为是C的超集合(Superset),但这并不严谨。大部分的C代码可以很轻易的在C++中正确编译,但仍有少数差异,导致某些有效的C代码在C++中失效,或者在C++中有不同的行为。
最常见的差异之一是,C允许从void*隐式转换到其它的指针类型,但C++不允许。下列是有效的C代码:
1 2 3 4 5 | //从void* 类型隐式转换为 int * 类型 int *i= malloc ( sizeof ( int )*5); |
但要使其在C和C++两者皆能运作,就需要使用显式转换:
1 | int *i=( int *) malloc ( sizeof ( int )*5); |
另一个常见的可移植问题是,C++定义了新关键字,例如如new,class,它们在C程序中可以作为识别字(例:变量名)的。
在C标准( )中去除了一些不兼容之处,也支持了一些C++的特性,如//注解,以及在代码中混合声明。不过C99也纳入几个和C++冲突的新特性(如:可变长度数组、原生复数类型和复合逐字常数)。
若要混用C和C++的代码,则所有在C++中调用的C代码,必须放在 extern "C" { /* C代码 */ } 内。
语言特点
优点
· C++设计成静态类型、和C同样高效且可移植的多用途程序设计语言。
· C++设计直接的和广泛的支持多种 (程序化程序设计、资料抽象化、 、泛型程序设计)。
C++代码 (2张)
· C++设计无需复杂的程序设计环境。 [7]
C++语言灵活,运算符的数据结构丰富、具有结构化控制语句、程序执行效率高,而且同时具有高级语言与汇编语言的优点,与其它语言相比 ,可以直接访问物理地址,与汇编语言相比又具有良好的可读性和可移植性。
总得来说,C++语言的主要特点表现在两个方面,一是尽量兼容C,二是支 持面向对象的方法。它操持了C的简洁、高效的接近汇编语言等特点,对C的类型系统进行了改革的扩充,因此C++比C更安全,C++的编译系统能检查出更多 的类型错误。另外,由于C语言的广泛使用,因而极大的促进了C++的普及和推广。
C++语言最有意义的方面是支持面向对象的特征。虽然与C的兼容使得C++具有双重特点,但他在概念上完全与C不同,更具面向对象的特征。
出于保证语言的简洁和运行高效等方面的考虑,C++的很多特性都是以库(如STL)或其他的形式提供的,而没有直接添加到语言本身里。关于此类话题, 的《C++语言的设计和演化》(1994)里做了详尽的陈述。
C++引入了面向对象的概念,使得开发人机交互类型的应用程序更为简单、快捷。很多优秀的程序框架包括 、 、 、 、 、 就是使用的C++。
缺点
C++由于语言本身复杂。C++的编译系统受到C++的复杂性的影响,非常难于编写,即使能够使用的编译器如果存在问题,可能难于被发现。
由于本身的复杂性,复杂的C++程序的正确性相当难于保证。
C++对于安全性也无法保证,所以,很容易依靠C++编译出病毒来。
数据类型
数据定义
数据是程序处理的对象,数据可以依其本身的特点进行分类。我们知道在数学 中有整数、实数的概念,在日常生活中需要用字符串来表示人的姓名和地址,有些问题的回答只能是“是”或“否”(即逻辑“真”或“假”)。不同类型的数据有 不同的处理方法,例如:整数和实数可以参加算术运算,但实数的表示又不同于整数,要保留一定的小数位;字符串可以拼接;逻辑数据可以参加“与”、“或”、 “非”等逻辑运算。
我们编写计算机程序,目的就是为了解决客观世界中的现实问题。所以,高级语言中也为我们提供了丰富的数据类型和运算。C++中的数据类型分为基本类型和自定义类型。基本类型是C++编译系统内置的。
基本类型
C++的基本数据类型如下表所示(下表中列出的各类型的长度和取值范围,是指以面向80x86处理器的 Viusal C++ 2012 和 gcc 4.8.1 的长度,其它的编译器并不一定是这个长度)。
bool所支持的字节数是1b,取值范围是false、true;
char、signed char所支持的字节数是1b,取值范围是-128~127;
unsign char所支持的字节数是1b,取值范围是0~255;
short (signed short)所支持的字节数是2byte,取值范围是-32768~32767;
unsigned short所支持的字节数是2byte,取值范围是0~65535;
int (signed int)所支持的字节数是4b,取值范围是-2147483648~2147483647;
unsigned int所支持的字节数是4b,取值范围是0~4294967295;
long (signed long)所支持的字节数是4b,取值范围是-2147483648~2147483647
unsigned long所支持的字节数是4b,取值范围是0~4294967295
unsigned long long所支持的字节数是8b,取值范围是0~18446744073709551615
float所支持的字节数是4b,取值范围是
double所支持的字节数是8b,取值范围是
long double所支持的字节数是8b,取值范围是
类型转换
C++丰富的数据类型允许根据需要选择不同的类型,这也使得计算机的操作更复杂。
自动类型转换(隐式类型转换)
在下列四种情况中计算机自动进行类型转换:
- 在混合类型的算术表达式中
- 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类型. }
强制类型转换(显示类型转换)
C++显式转换包含四种转换:
- :用法:static_cast < type-id > ( expression )说明:该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。
- :用法:dynamic_cast < type-id > (expression)说明:该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void*;
- :用法:const_cast<type_id> (expression)说明:该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
- :用法:reinterpret_cast<type-id> (expression)说明:type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
编程技巧
new和delete
new和delete提供了存储的动态内存分配和释放功能,它的作用相当于C语言的函数malloc()和free(),但性能更为优越。使用new较之使用malloc()有以下的几个优点:
(1)new自动计算要分配类型的大小,不使用sizeof运算符,比较省事,可以避免错误。
(2)自动地返回正确的 类型,不用进行强制指针 。
(3)可以用new对分配的对象进行 。 [8]
inline
对于频繁使用的函数,C语言建议使用宏调用代替 以加快代码执行,减少调用开销。但是宏调用有许多的弊端,可能引起不期望的副作用。例如宏:#define abs(a)(a)<0?(-a):(a)),当使用abs(i++)时,这个宏就会出错。
所以在C++中应该使用 替代宏调用,这样既可达到宏调用的目的,又避免了宏调用的弊端。
使用内联函数只须把inline关键字放在函数返回类型的前面。 [8]
函数重载
在C语言中,两个函数的名称不能相同,否则会导致编译错误。而在C++中,函数名相同而参数数据类型不同或参数个数不同或二者皆不同的两个函数被解释为重载。
使用 可以帮助程序员处理更多的复杂问题,避免了使用诸如intabs()、fabs()、dabs()等繁杂的函数名称;同时在大型程序中,使函数名易于管理和使用,而不必绞尽脑汁地去处理函数名。同时必须注意,参数数据类型相同,但是函数返回类型不同的两个函数不能重载。 [8]
参数传递
在C语言中,如果一个函数需要修改用作参数的变量值的时候 ,参数应该声明为指针类型;当参数的大小超过一个机器字长时,通过传值方式来传递参数的效率较低,也需要用指针。由于C语言的指针可以进行p++,-- p,p+=1等算术运算,所以编译器无法在编译的时候确定指针引用的变量。对于复杂的程序,使用 容易出错,程序也难以读懂。在C++中,对于上述情况 可以使用引用来代替指针,使程序更加清晰易懂。引用就是对变量取的一个别名,对引用进行操作,这就相当于对原有变量进行操作。 [8]
缺省参数
在C++中函数可以使用 。
通常的情况下,一个函数应该具有尽可能大的灵活性。使用缺省参数为程序员处理更大的复杂性和灵活性问题提供了有效的方法,所以在C++的代码中都大量地使用了缺省参数。
需要说明的是,所有的缺省参数必须出现在不缺省参数的右边。亦即,一旦开始定义缺省参数,就不可再声明非缺省的参数。否则当你省略其中一个参数的时候,编译器无法知道你是自定义了这个参数还是利用了缺省参数而定义了非缺省的参数。 [8]
使用STL
STL(Standard Template Library, ),STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator( ),并包括一些工具类如 。几乎所有的代码都采用了 和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
作用符被重载,使得我们可以像访问数组一样访问vector中的元素。 [8]
使用模板
模板的概念
模板是C++的一个特性,是函数和类可以作用于不同的类型上而不需要针对每一个具体类型重复相同的代码。与模板相反,我们已经学过的 重载(Overloading),对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同。正确的调用 。例如,为求两个数的最大值,我们定义MAX()函数需要对不同的数据类型分别定义不同 重载(Overload)版本。如果使用模板就可以只写一个通用的MAX模板,而不需要针对每个类型重复相同的逻辑。
指针与引用的区别
指针与引用看上去完全不同(指针用操作符“*”和“->”,引用使用操作符“&”),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?
首先,要认识到在任何情况下都不能使用指向空值的引用。一个引用必须总是 指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空 值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
类和对象
是具有相同属性和相同的方法的对象的集合,它是一种既包含数据又包含函数的抽象数据类型。
对象是类进行实体化后的产物,是一个实体。
在C++中也是先声明一个类类型,然后用它去定义若干个同类型的对象。对象就是类类型的一个变量。可以说类是对象的模板,是用来定义对象的一种抽象类型。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
声明类类型
类是用户自己指定的类型。如果程序中要用到类类型,必须自己根据需要进行声明,或者使用别人已设计好的类。C++标准本身并不提供现成的类的名称、结构和内容。
在C++中声明一个类的类型和声明一个结构体类型是相似的。下面是声明一个结构体类型的方法:
1 2 3 4 5 6 7 | struct Student //声明了一个名为Student的结构体类型 { int num; char name[20]; char sex; }; Student stud1,stud2; //定义了两个结构体变量stud1和stud2,它只包括数据,没有包括操作 |
声明一个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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.
可以看到声明类的方法是由声明结构体类型的方法发展而来的,类就是对象的类型。实际上,类是一种广义的数据类型。类这种数据类型中的数据既包含数据,也包含操作数据的函数。
不能把类中的全部成员与外界隔离,一般是把数据隐蔽起来,而把成员函数作为对外界的 。可以将上面类的声明改为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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,则系统就默认为是私有的。归纳以上对类类型的声明,可得到其一般形式如下:
1 2 3 4 5 6 7 8 | class 类名 { private : //私有的数据和成员函数; public : //公用的数据和成员函数; }; |
private 和public称为成员访问限定符(member access specifier)。除了private和public之外,还有一种成员访问限定符protected(受保护的),用protected声明的成员 称为受保护的成员,它不能被类外访问(这点与私有成员类似),但可以被派生类的成员函数访问。
在声明类类型时,声明为private的成员和声明为public的成员的次序任意,既可以先出现private部分,也可以先出现public部分。
在一个类体中,关键字private和public可以分别出现多次。每个部分的有效范围到出现另一个访问限定符或类体结束时(最后一个右花括号)为止。但是为了使程序清晰,应该养成这样的习惯: 使每一种成员访问限定符在类定义体中只出现一次。
C++ 程序多数先写public部分,把private部分放在类体的后部。这样可以使用户将注意力集中在能被外界调用的成员上,使阅读者的思路更清晰一些。
在C++程序中,经常可以看到类。为了用户方便,常用的C++编译系统往往向用户提供 (但不属于C++语言的组成部分),内装常用的基本的类,供用户使用。不少用户也把自己或本单位经常用到的类放在一个专门的类库中,需要用时直接调用,这样就减少了程序设计的工作量。
定义对象
上述程序段中,最后一行用已声明的Student类来定义对象,这种方法是很容易理解的。经过定义后,stud1和stud2就成为具有Student类特征的对象。stud1和stud2这两个对象都分别包括Student类中定义的数据和函数。
定义对象也可以有以下几种方法:
1.先声明类类型,然后再定义对象前面用的就是这种方法,如Student stud1,stud2;//Student是已经声明的类类型在C++中,声明了类类型后,定义对象有两种形式。
(1)class 类名 对象名
如: class Student stud1,stud2;
把class和Student合起来作为一个类名,用来定义对象。
(2)类名 对象名
如: Student stud1,stud2;
直接用类名定义对象。
这两种方法是等效的。第1种方法是从C语言继承下来的,第2种方法是C++的特色,显然第2种方法更为简捷方便。
2.在声明类类型的同时定义对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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; //定义了两个Student类的对象 |
在定义Student类的同时,定义了两个Student 类的对象。
3.不出现类名,直接定义对象
1 2 3 4 5 6 7 | class //无类名 { private : //声明以下部分为私有的 //... public : //声明以下部分为公用的 //... }stud1,stud2; //定义了两个无类名的类对象 |
直接定义对象,在C++中是合法的、允许的,但却很少用,也不提倡用。在实际的程序开发中,一般都采用上面3种方法中的第1种方法。在小型程序中或所声明的类只用于本程序时,也可以用第2种方法。在定义一个对象时,编译系统会为这个对象分配存储空间,以存放对象中的成员。
类和结构体
C++增加了class类型后,仍保留了结构体类型(struct ),而且把它的功能也扩展了。C++允许用struct来定义一个类型。如可以将前面用关键字class声明的类类型改为用关键字struct:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | structStudent{ //用关键字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; //定义了两个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++所保留的关键字。
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 |
编程开发
代码实现
一个程序从编写到最后得到运行结果要经历以下一些步骤:
1、用C++语言编写程序
用 编写的程序称为“ ”(source program)。源程序的后缀取决于C++实现,下表列出了常用扩展名:
Unix: | C, cc, cxx, c |
GNU C++: | C, cc, cxx, cpp, c++ |
Digital Mars: | cpp, cxx |
Borland: | C++ cpp |
Watcom: | cpp |
Microsoft Visual C++: | cpp, cxx, cc |
Metrowerks CodeWarrior: | cpp, cp, cc, cxx, c++ |
2、对源程序进行编译
为了使计算机能执行高级语言源程序,必须先用一种称为“ (complier)”的软件(也称编译程序或编译系统),把源程序翻译成二进制形式的“目标程序(object program)。
编译是以源程序文件为单位分别编译的。目标程序一般以.obj或.o作为 后缀(object 的缩写)。编译的作用是对源程序进行词法检查和语法检查。编译时对文件中的全部内容进行检查,编译结束后会显示出所有的编译出错信息。一般编译系统给出的 出错信息分为两种,一种是错误(error);一种是警告(warning) 。
3、将目标文件连接
在改正所有的错误并全部通过 后,得到一个或多个目标文件。此时要用系统提供的“连接程序(linker)”将一个程序的所有目标程序和系统的库文件以及系统提供的其他信息连接起来,最终形成一个可执行的二进制文件,它的后缀是.exe,是可以直接执行的。
4、运行程序
运行最终形成的可执行的二进制文件(.exe文件),得到运行结果。
如果运行结果不正确,应检查程序或算法是否有问题。
命令行开发方式
在Unix世界有大量的程序员是传统的非IDE的方式进行软件开发。一般是如下组合:
1.编译器: 和 等。 [9]
2.编辑器:常用 和
3.make:GNU make 或者BSD的pmake等,功能与用法基本一样
4.版本管理: , ,git等等
5.代码阅读: ,ctags,lxr等
集成开发环境(IDE)
1. (Visual C++)
2.Borland C++ Builder
3. (Myln + CDT + MinGW32 + GCC)
Visual Studio 2012 (2张)
4. (MinGW32 + GCC) 5. (可配合多款编译器使用)
6.
7.
8. (可配合多款编译器使用)
9.
实际上,当前流行的编译器只有五种:Intel C++ 编译器、微软的cl.exe编译器(捆绑于Visual Studio套装中)、GNU的GCC编译器、LLVM的Clang编译器、Borland公司的bcc.exe编译器(捆绑于Borland C++ Builder套装中)。
多泛型设计
根据Effective C++第三版第一条款的描述,C++由以下四个“子语言”组成:
1、C子语言。C++支持C语言的几乎全部功能,主要是c89的部分,在语法上与C语言仅有极微妙的差别(如括号表达式的左右值性,具体请参考C++标准文献)。这部分功能对应于传统的面向过程的编程泛型,并提供了面向函数编程泛型的基础。
2、 的C++语言。C++语言原本不具备面向对象的设计功能,然而随着 的概念的普及,C++语言也开发出了支持面向对象功能的版本。这部分功能对应于面向对象的编程泛型。
3、泛型编程语言。C++强大(但容易失控的)模板功能使它能在编译期完成许多工作,从而大大提高运行期效率,并且大大提高了C++的表达能力。 (C++ 标准模板库,Standard Template Library)是一个基于模板技术的库。随着STL的不断发展,它已经逐渐成为C++程序设计中不可或缺的部分,其效率可能比一般的native代码低 些,但是其安全性与规范性使它大受欢迎。模板使C++能够支持泛型编程(generic programming)和生成式编程(generative programming)的泛型。
4、在C++11中引入的Lambda,使得程序员可以定义匿名函数,完善了C++对于面向函数的编程泛型的支持。
经典著作
入门书籍
《C++ Primer 中文版(第5版)》
《C++ Primer (Fifth Edition)》
《C++ Primer Plus 中文版(第六版)》
《C++ Primer Plus (Sixth Edition)》
进阶书籍
《Thinking in C++》
《A Tour Of C++》
《C++编程思想》
《The C++ Programming Language (Fourth Edition)》
《C++程序设计语言(第四版)》(未出版)
《Essential C++》
《The C++ Standard Library: A Tutorial and Reference》
《C++标准程序库:自修教程与参考手册》
《Effective STL》
《Generic Programming and the STL: Using and Extending the C++ Standard Template Library》
《泛型编程与STL》
《C++语言的设计和演化》
《C++标准程序库:自修教程与参考手册》
《STL源码剖析》
高阶书籍
《Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference》
《标准C++输入输出流与本地化》
《C++ Network Programming》
《C++网络编程》
《Ruminations on C++: A Decade of Programming Insight and Experience》
《C++沉思录》
《Inside The C++ Object Model》
《深度探索C++对象模型》
《Design Patterns:Elements of Reusable Object-Oriented software》
《设计模式:可复用面向对象软件的基础》
《Large-Scale C++ Software Design》(《大规模C++程序设计》);
《STL 源码剖析》;
《The C++ Standard : Incorporating Technical Corrigendum No. 1》;
《Preprocessor C++》
《C++语言基础》
《Essential C++》
《(More)Effective C++》
《(More)Exceptional C++》 [10]
《C++ Templates》
《Core C++ A Software Engineering Approach》 [11]
《高质量C++编程指南——上海贝尔标准编程文档 》
Presentation Materials: Overview of the New C++ (C++11/14) [12]
常见错误
英文 | 参考译文 |
---|---|
Ambiguous operators need parentheses | 模棱两可的操作符需要括号 |
Ambiguous symbol ''xxx'' | 不明确的符号 |
Argument list syntax error | 参数表语法错误 |
Array bounds missing | 数组界限符丢失 |
Array size toolarge | 数组尺寸太大 |
Bad character in paramenters | 参数中有不适当的字符 |
Bad file name format in include directive | 包含命令中文件名格式不正确 |
Bad ifdef directive synatax | 编译预处理ifdef有语法错 |
Bad undef directive syntax | 编译预处理undef有语法错 |
Bit field too large | 位字段太长 |
Call of non-function | 调用未定义的函数 |
Call to function with no prototype | 调用函数时没有函数的说明 |
Cannot modify a const object | 不允许修改常量对象 |
Case outside of switch | 漏掉了case 语句 |
Case syntax error | Case 语法错误 |
Code has no effect | 代码不可能被执行到 |
Compound statement missing{ | 分程序漏掉"{" |
Conflicting type modifiers | 互相冲突的类型说明符设置 |
Constant expression required | 需要常量表达式 |
Constant out of range in comparison | 在比较中常量超出范围 |
Conversion may lose significant digits | 转换时会丢失数值的精度 |
Conversion of near pointer not allowed | 不允许转换近指针 |
Could not find file ''xxx'' | 找不到XXX文件 |
Declaration missing ; | 声明中缺少";" |
Declaration syntax error | 声明中出现语法错误 |
Default outside of switch | Default 出现在switch语句之外 |
Define directive needs an identifier | 定义编译预处理需要标识符 |
Division by zero | 用零作除数 |
Do statement must have while | Do-while语句中缺少while部分 |
Enum syntax error | 枚举类型语法错误 |
Enumeration constant syntax error | 枚举常数语法错误 |
Error directive :xxx | 错误的编译预处理命令 |
Error writing output file | 写输出文件错误 |
Expression syntax error | 表达式语法错误 |
Extra parameter in call | 调用时出现多余错误 |
File name too long | 文件名太长 |
Function call missing | 函数调用缺少右括号 |
Fuction definition out of place | 函数定义位置错误 |
Fuction should return a value | 函数必需返回一个值 |
Goto statement missing label | Goto语句没有标号 |
Hexadecimal or octal constant too large | 16进制或8进制常数太大 |
Illegal character ''x'' | 非法字符x |
Illegal initialization | 非法的初始化 |
Illegal octal digit | 非法的8进制数字 |
Illegal pointer subtraction | 非法的指针相减 |
Illegal structure operation | 非法的结构体操作 |
Illegal use of floating point | 非法的浮点运算 |
Illegal use of pointer | 指针使用非法 |
Improper use of a typedefsymbol | 类型定义符号使用不恰当 |
In-line assembly not allowed | 不允许使用行间汇编 |
Incompatible storage class | 存储类别不相容 |
Incompatible type conversion | 不相容的类型转换 |
Incorrect number format | 错误的数据格式 |
Incorrect use of default | Default使用不当 |
Invalid indirection | 无效的间接运算 |
Invalid pointer addition | 指针相加无效 |
Irreducible expression tree | 无法执行的表达式运算 |
Lvalue required | 需要逻辑值0或非0值 |
Macro argument syntax error | 宏参数语法错误 |
Macro expansion too long | 宏的扩展以后太长 |
Mismatched number of parameters in definition | 定义中参数个数不匹配 |
Misplaced break | 此处不应出现break语句 |
Misplaced continue | 此处不应出现continue语句 |
Misplaced decimal point | 此处不应出现小数点 |
Misplaced elif directive | 不应编译预处理elif |
Misplaced else | 此处不应出现else |
Misplaced else directive | 此处不应出现编译预处理else |
Misplaced endif directive | 此处不应出现编译预处理endif |
Must be addressable | 必须是可以编址的 |
Must take address of memory location | 必须存储定位的地址 |
No declaration for function ''xxx'' | 没有函数xxx的说明 |
No stack | 缺少堆栈 |
No type information/没有类型信息 | 缺少堆栈 |
Non-portable pointer assignment | 不可移动的指针(地址常数)赋值 |
Non-portable pointer comparison | 不可移动的指针(地址常数)比较 |
Non-portable pointer conversion | 不可移动的指针(地址常数)转换 |
Not a valid expression format type | 不合法的表达式格式 |
Not an allowed type | 不允许使用的类型 |
Numeric constant too large | 数值 大 |
Out of memory | 内存不够用 |
Parameter ''xxx'' is never used | 能数xxx没有用到 |
Pointer required on left side of -> | 符号->的左边必须是指针 |
Possible use of ''xxx'' before definition | 在定义之前就使用了xxx(警告) |
Possibly incorrect assignment | 赋值可能不正确 |
Redeclaration of ''xxx'' | 重复定义了xxx |
Redefinition of ''xxx'' is not identical | xxx的两次定义不一致 |
Register allocation failure | 寄存器定址失败 |
Repeat count needs an lvalue | 重复计数需要逻辑值 |
Size of structure or array not known | 结构体或数给大小不确定 |
Statement missing ; | 语句后缺少";" |
Structure or union syntax error | 结构体或联合体语法错误 |
Structure size too large | 结构体尺寸太大 |
Sub scripting missing ] | 下标缺少右方括号 |
Superfluous & with function or array | 函数或数组中有多余的"&" |
Suspicious pointer conversion | 可疑的指针转换 |
Symbol limit exceeded | 符号超限 |
Too few parameters in call | 函数调用时的实参少于函数的参数不 |
Too many default cases | Default太多(switch语句中一个) |
Too many error or warning messages | 错误或警告信息太多 [13] |
英文 | 参考译文 |
---|---|
Too many type in declaration | 说明中类型太多 |
Too much auto memory in function | 函数用到的局部存储太多 |
Too much global data defined in file | 文件中全局数据太多 |
Two consecutive dots | 两个连续的句点 |
Type mismatch in parameter xxx | 参数xxx类型不匹配 |
Type mismatch in redeclaration of ''xxx'' | xxx重定义的类型不匹配 |
Unable to create output file ''xxx'' | 无法建立输出文件xxx |
Unable to open include file ''xxx'' | 无法打开被包含的文件xxx |
Unable to open input file ''xxx'' | 无法打开输入文件xxx |
Undefined label ''xxx'' | 没有定义的标号xxx |
Undefined structure ''xxx'' | 没有定义的结构xxx |
Undefined symbol ''xxx'' | 没有定义的符号xxx |
Unexpected end of file in comment started on line xxx | 从xxx行开始的注解尚未结束文件不能结束 |
Unexpected end of file in conditional started on line xxx | 从xxx 开始的条件语句 尚未结束文件不能结束 |
Unknown assemble instruction | 未知的汇编结构 |
Unknown option | 未知的操作 |
Unknown preprocessor directive: ''xxx'' | 不认识的预处理命令xxx |
Unreachable code | 无路可达的代码 |
Unterminated string or character constant | 字符串缺少引号 |
User break | 用户强行中断了程序 |
Void functions may not return a value | Void类型的函数不应有返回值 |
Wrong number of arguments | 调用函数的参数数目错 |
''xxx'' not an argument | xxx不是参数 |
''xxx'' not part of structure | xxx不是结构体的一部分 |
xxx statement missing ( | xxx语句缺少左括号 |
xxx statement missing ) | xxx语句缺少右括号 |
xxx statement missing ; | xxx缺少分号 |
xxx'' declared but never used | 说明了xxx但没有使用 |
xxx'' is assigned a value which is never used | 给xxx赋了值但未用过 |
Zero length structure | 结构体的长度为零 [14] |
争议
“在这12年里,C++用户人数大约每七个月半增加一倍”是许多C++相 关文件必引的一段话;然而,时至今日新语言层出不穷,用户人数已不太可能以如此速度增长。分析机构EvansData定期对开发人员展开调查,其数据显 示,以C++为工具的开发人员在整个开发界所占的比例由1998年春天的76%下降至2004年秋的46%。Forrester最新的调查显示,C++、 微软 和Java是众多公司产品体系的首选语言。对100家公司的调查显示,C/C++、Visual Basic和Java在产品体系中的使用比例分别是59%、61%和66%。
一部分Unix/C程序员对C++语言深恶痛绝,他们批评的理由如下:
1 STL以非常丑陋的方式封装了各种数据结构和算法,写出来的代码难以理解、不美观。
2 C++编译器复杂和不可靠,不适合构建人命关天类型的程序。
3 一部分人认为 技术徒增学习成本,不如面向过程的C语言简单容易使用,尤其是在系统软件的构建上。
概括说来 程序员批评C++主要是由于UNIX社区与C++社区的文化差异。[6]
一个值得注意的事情是 之父 曾经炮轰C++; 得主尼克劳斯·维尔特也曾经批评C++语言太复杂、语法语义模糊,是“拙劣工程学”的成果。
事实上,对于C++语言的批评并不只来源于Unix/Unix-Like系统下的程序员。就像C++语言本身是一个跨平台的语言一样,对C++的批评并不局限于Unix/Unix-Like系统用户。
一个确定的观点是:C++是一门复杂的语言、这门语言拥有过多的特性从而难以彻底掌握;C++的某些库难以学习、掌握并应用于实际当中;很多程序员都认为C++是一个过度设计的程序语言。
C++ 标准
C++ 98 标准
C++标准第一版,1998年发布。正式名称为 ISO/IEC 14882:1998 [15] 。
绝大多数编译器都支持C++98标准。不过当时错误地引入了export 关键字。由于技术上的实现难度,除了Comeau C++编译器export关键字以外,没有任何编译器支持export关键字。并且这个标准对现代的一些编译理念有相当的差距,有很多在高级语言都应当有 的功能,它都没有。这也正是后来需要制定C++11标准的原因所在。
C++ 03 标准
C++标准第二版,2003年发布。正式名称为 ISO/IEC 14882:2003 [16] 。这个标准仅仅是C++98修订版,与C++98几乎一样,没做什么修改。仅仅是对C++98做了一些“勘误”,就连主流编译器(受C99标准影响)都已支持的long long都没有被加入C++03标准。
C++ 11 标准
C++标准第三版,2011年8月12日发布。正式名称为 ISO/IEC 14882:2011 [17] 。
由C++标准委员会于2011年8月12日公布,并于2011年9月出 版。2012年2月28日的国际标准草案(N3376)是最接近于现行标准的草案(编辑上的修正)。C++11包含了核心语言的新机能,并且拓展C++标 准程序库,并且加入了大部分的C++ Technical Report 1程序库(数学上的特殊函数除外)。此次标准为C++98发布后13年来第一次重大修正。
注意: C++11标准(ISO/IEC 14882:2011)与 C11标准(ISO/IEC 9899:2011)是两个完全不同的标准,后者是C语言的标准。
C++ 14 标准
C++标准第四版,2014年8月18日发布。正式名称为 ISO/IEC 14882:2014。
2014年8月18日,ISO组织在其网站上发布文章称:
C++ 作者 Bjarne Stroustrup 称,主要的编译器开发商已经实现了 C++ 14 规格。
C++ 14 是 C++ 11 的增量更新,主要是支持普通函数的返回类型推演,泛型 lambda,扩展的 lambda 捕获,对 constexpr 函数限制的修订,constexpr变量模板化等等。
C++14是C++语言的最新标准,正式名称为" International Standard ISO/IEC 14882:2014(E) Programming Language C++"。C++14旨在作为C++11的一个小扩展,主要提供漏洞修复和小的改进。C++14标准的委员会草案(Committee Draft)N3690于2013年5月15日发表 [18] 。工作草案(Working Draft)N3936已于2014年3月02日完成。最终的投票期结束于2014年8月15日,结果(一致通过)已于8月18日公布。