精读笔记之进入C++
要建造简单的房屋,首先要打地基、大框架。如果一开始没有牢固的结构,后面就很难建造窗子、门框、圆屋顶和镶木地板的歌舞厅等。同样,学习计算机语言时,应从程序的基本结构开始学起。
首先介绍一个显示消息的简单C++程序。
- 程序清单使用C++工具cout生成字符输出;
- 源代码中包含了一些供读者阅读的注释,以//打头,编译器会将//后面的内容忽视;
- C++对大小写敏感,即区分大小写字母,亦即如果将程序中的cout替换为Cout或COUT,程序将无法通过编译并提示使用了未知的标识符。
- 文件扩展名cpp是一种表示C++程序的常用方式。
#include<iostream> //a PREPROCESSOR directive
int main() //function header
{ //start of function body
using namespace std; //make definitions visible
cout << "Come up and C++ me some time."; //message
cout << endl; //start a new line
cout << "You won't regret it!" << endl; //more output
return 0; //terminate main()
} //end of function body
事实上,C++也能够使用pintf()、scanf()和其他所有标准C输入和输出函数,只需要包含常规C语言的stdio.h文件。
上段代码示例非常简单,包含一下基本元素:
- 注释,由前缀//标识;
- 预处理编译指令#include;
- 函数头:int main();
- 编译指令 using namespace;
- 函数体,用{}括起来;
- 使用C++的cout工具显示消息的语句;
- 结束mian()函数的return语句。
-
main()函数
上个示例程序的基本结构如下:
int main()
{
statements
return 0;
}
这几行表示有一个名为main()的函数,并描述了该函数的行为。这几行代码构成了函数定义(function)。该定义由两部分组成:第一行 int main()叫函数头(function head),花括号({和})中包含的部分叫函数体。函数体是指出函数应该做什么的计算机指令,所有的语句都以分号;结束。
main函数中最后一条语句叫返回语句,它结束该函数。
就目前而言,C++语法要求main函数的定义以函数int main()开始。C++函数可以给调用函数返回一个值,这个值叫作返回值。在这里,从关键字int可知,main()返回一个整数值。接下来是空括号。通常C++函数在调用另一个函数时,可以将信息传递给函数。括号中的函数头部分描述的就是这种信息。在这里,空括号意味着main()函数不接受任何信息,或者main()不接受任何参数。int main()表明main()函数可以给调用它的函数返回一个整数值,且不从调用它的函数那里获得任何信息。
在C语言中,省略返回类型相当于说函数的类型为int。然而C++逐步淘汰了这种用法,也可以使用下面的变体:
int main(void)
括号中使用关键字void明确指出,函数不接受任何参数。有些程序员使用下面的函数头,并省略返回语句:
void main() -
C++注释
C++注释以双斜杠(//)打头,注释是程序员为读者提供的说明,通常标识程序的一部分或解释代码的某个方面。
注释可以位于单独的一行上,也可以和代码位于同一行。
C++也能识别C注释,C注释包括在符号/* 和 */之间,可以跨越多行。 -
C++预处理器和iostream文件
如果程序要使用C++输入或输出工具,应提供这样两行代码:
#include < iostream>
using namespace std;
这里使用这行代码旨在简化该程序。
C++和C一样,也使用一个预处理器,该程序在进行主编译之前对源文件进行处理,不必执行任何特殊的操作来调用该预处理器,它会在编译程序时自动运行。
#indclude < iostream>
该编译指令使预处理器将iostream文件内容添加到程序中。这是一种电典型的预处理器操作:在代码被编译之前,替换或添加文本。
iostream中的io指的是输入和输出。C++中的输入输出方案涉及iostream文件中的多个定义。为了使用cout来显示消息,第一个程序需要这些定义。#include编译指令导致iostream文件的内容随原代码文件的内容一起被发送给编译器。实际上,iostream文件的内容将取代程序中的代码行#include< iostream>。原始文件没有被修改,而是将源代码文件和iostream组合成一个符合文件,编译的下一阶段将使用该文件。 -
头文件名
像iostream这样的文件叫做包含文件——由于他们被包含在其他文件中;也叫头文件——由于他们被包含在文件起始处。C++编译器自带了很多头文件,每个头文件都支持一组特定的工具。C语言的传统是,头文件使用扩展名h,将其作为一种通过名称标识文件类型的简单方式。但是C++的用法变了,对老式C的头文件保留了扩展名h,而C++头文件则没有扩展名。有些C头文件被转换成C++头文件,这些头文件被重新命名,去掉了扩展名h,并在文件名称前加上前缀c(表明来自C语言)。 -
名称空间
名称空间支持是一项C++特性,旨在让编写的程序或将多个厂商现有代码组合程序时更容易。例如可能使用两个已经封装好的产品,而他们都包含一个同名函数,此时编译器编译就会发生错误。名称空间让厂商能够将各自的产品封装在各自的名称空间中,以此区分同名函数、类或变量。这样,Microflop空间中的wanda()函数全称应为:Microflop::wanda(),同样,Piscine空间中的wanda()全称应为:Piscine::wanda()。
using namespace std;
上述代码可以使得std中的cin、cout等直接被使用而无需加上std::的前缀。 -
使用cout进行C++输出
在一条输出语句中:
cout << “Come up and C++ me some time.”;
双引号括起来的部分是要打印的消息。在C++中,用双引号括起来的一系列字符叫做字符串。<<表示该语句将这个字符串发送给cout;该符号指出了信息流的的路径。
控制符endl:
endl是一个特殊的C++符号,在输入输出流中插入endl将导致屏幕光标移到下一行开头。
打印字符时,cout不会自动移到下一行,第一条cout语句将光标留在输出字符串后面。每条cout语句的输出从前一个输出的末尾开始。
换行符:
C++还提供了另一种在输出中指示换行的旧式方法:C语言符号\n:
cout << “What’s next?\n”;
\n被视为一个字符,名为换行符。
显示字符串时,在字符串中包含换行符,而不是在末尾加上endl,可以减少输入量。
- C++原代码的格式化
有些语言(如FORTRAN)是面向行的,即每条语句占一行。对于这些语言来说,回车的作用是将语句分开。然而,在C++中,通常可以在能够使用回车的地方使用空格,反之亦然。这说明既可以把一条语句放在几行上,也可以把几条语句放在一行上。
C++语句
#include <iostream>
int main(){
using namespace std;
int carrots;
carrots = 25;
cout << "I have ";
cout << carrots;
cout << " carrots.";
cout << endl;
carrots = carrots -1;
cout << "Now I hava " << carrots <<" carrots."<< endl;
return 0;
}
由上段代码可见,与printf()相比,cout能够识别数据类型,其设计更灵活、更好用。
输出时,<<运算符将字符串插入到输出流;输入时,cin使用>>运算符从输入流中抽取字符。与cout一样,cin也是一个智能对象。它可以将通过键盘输入的一系列字符转换为接受信息的变量能够接受的形式。
类简介
类是用户定义的一种数据类型。要定义类,需要描述它能够 表达什么信息和可对数据执行哪些操作。类之于对象就像类型之于变量。也就是说,类定义描述的是数据格式及其用法,而对象则是根据数据格式规范创建的实体。
例如:
int carrots;
该段代码将创建一个类型为int的变量;同样,cin是一个istream类对象。
函数
C++函数分两种:有返回值的和没有返回值的。
-
有返回值的函数
有返回值的函数将生成一个值,而这个值可以赋给变量或者在其他表达式中使用。例如,标准C/C++库包含一个名为sqrt()的函数,它返回平方根。假设要计算6.25的平方根,并将结果赋值给变量x:
x = sqrt(6.25);
表达式sqrt(6.25)被称为函数调用,被调用的函数叫做被调用函数,包含函数调用的函数叫做调用函数,圆括号中的值是发送给函数的信息,这被称为传递给函数,以这种方式发送给函数的值叫做参数。
在使用函数之前,C++编译器必须知道函数的参数类型和返回值类型。C++程序应当为程序中使用的每个函数提供原型。
在程序中使用sqrt()时,也必须提供函数原型,可以用两种方法实现:
- 在原代码文件中输入函数原型;
- 包含头文件cmath(老系统为math.h),其中定义了原型。
应在首次使用函数之前提供其原型。通常的做法时把原型放在main()函数定义的前面。
如下演示库函数sqrt()的用法,它通过包含cmath文件来提供函数的原型:
#include <iostream>
#include <cmath>
int main(){
using namespace std;
double area;
cout <<"Enter the floor area, in sqare feet, of your home: ";
cin >> area;
double side;
side = sqrt(area);
cout << "That's the equivalent of a square " << side <<" feet to the side." << endl;
return 0;
}
C++允许在程序的任何地方声明新变量,因此sqrt.cpp在要使用side时才声明它。C++还允许在创建变量时对它进行赋值,因此也可以这样做:
double side = sqrt(area);
这个过程叫做初始化。
- 用户定义的函数
标准C库提供了140多个预定义的函数。如果其中的函数能满足要求,则应使用它们。但用户常常需要编写自己的函数,尤其是在设计类的时候。
前面已经使用过好几个用户定义的函数,它们都叫main()。每个C++程序都必须有一个main()函数,用户必须对它进行定义。假设需要添加另一个用户定义的函数,和库函数一样,也可以通过函数名来调用用户定义的函数。对于库函数,在使用之前必须提供其原型,通常把原型放到main()定义之前。但必须提供函数的源代码,最简单的方法是,讲代码放在main()后面。下段程序演示了函数定义和调用:
#include<iostream>
void simon(int);
int main(){
using namespace std;
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
return 0;
}
void simon(int n){
using namespace std;
cout << "Simon says touch your toes "<< n <<" times." << endl;
}
-
函数格式
在上个程序中,simon()函数的定义与main()的定义采用的格式相同。首先,有一个函数头;然后是花括号中的函数体。可以把函数的格式统一为如下的形式:
type functionname(argumentlist)
{
statements
}
注意,定义simon()的源代码位于main()的后面。和C一样(但不同于Pascal),C++不允许讲函数定义嵌套在另一个函数定义中。每个函数定义都是独立的,所有函数的创建都是平等的。 -
函数头
在上个程序中,simon()函数的函数头如下:
void simon(int n)
开头的void表明simon()没有返回值,因此调用simon()不会生产可在main()中将其赋值给变量的数字。因此,第一个函数调用如下:
simon(3);
括号中的int n表明,使用simon()时,应提供一个int参数。n是一个新的变量,函数调用时传递的值将被赋给它。因此,下面函数调用将3赋给simon()函数头中定义的年龄n:
simon(3);
当函数体中的cout语句使用n时,将调用函数调用时传递的值。这就是为什么simon(3)在输出中显示3的原因所在。
- 用户定义的有返回值的函数
再深入一步,编写一个使用返回语句的函数。main()函数已经揭示了有返回值的函数的格式,在函数头指出返回类型,在函数体结尾使用return。如下示例程序:
#include<iostream>
int stonetolb(int);
int main(){
using namespace std;
int stone;
cout << "Enter the weight in stone: ";
cin >> stone;
int pounds = stonetolb(stone);
cout << stone <<" stone = ";
cout << pounds << " pounds." << endl;
return 0;
}
int stonetolb(int sts){
return 14*sts;
}
在main()中,程序使用cin来给整型变量stone提供一个值,这个值被作为参数传递给stonetolb()函数。在该函数中,这个值被赋给变量sts。然后,stonetolb()用关键字return将14*sts返回给main()。这表明return后面并非一定得跟一个简单的数字。这里通过使用较为复杂的表达式,避免了创建一个新变量,将结果赋给变量,然后将它返回。程序将计算表达式的值返回。