《C++ Primer Plus》第二章

第一个C++程序

#include <iostream>
int main()
{
	using namespace std;
	cout << "hello.";
	cout << endl;
	return 0;
}

在某些窗口环境下,程序会在独立窗口执行然后直接结束自动关闭。所以可以在return语句前加上cin.get()来阻塞程序。

方法头

int main()

这个就是方法头,最左边的int是方法返回值的类型,main是方法的名字,括号内是调用该方法需要传入的参数的类型和个数。这里没写意味着该方法不需要传入参数。更清晰的写法应该是:

int main(void)

注释

使用双斜杠"//“作为开头来写一句注释。注释是用于给代码的读者解释代码的,编译器在编译程序时会忽略这些注释。
从//开始一直到该行结束都算是注释。所以注释可以单独写一行也可以写在一行代码的后面。
另外,C++也可以使用”/“和”/"来标记一段注释的开始和结束。这样的标记法就允许编写多行的注释。

//第一个C++程序
#include <iostream>
int main() //方法头
{
	using namespace std;
	cout << "hello.";
	cout << endl;
	return 0;
	/*
	多
	行
	注
	释
	*/
}

预处理和iostream

#include <iostream>

这一句将iostream文件的内容加到了程序中。这是典型的预处理行为:在编译之前添加或替换源代码的文本。也就是在程序被编译时,include这一句会被iostream的文件内容替代。
至于这样做的目的,是因为cout和cin都是在iostream文件中定义的对象,要使用这两个对象,就要引入iostream文件。

头文件(head file)

iostream被称作引入文件也称作头文件。C++有很多头文件,欸一个都包含了大量实用工具。C语言用h这个扩展名来简单区分头文件的名字与类型。比如C语言中math.h是支持多种数学方法的头文件。现在h扩展名在C语言的头文件中还有保留,C++也可以用,但C++的头文件都是没有扩展名的。C++很多头文件都是将C的头文件的扩展名去掉然后在前面加一个’c’。比如math.h变成cmath.

命名空间(namespace)

如果程序引入的不是iostream.h二十iostream,那么就需要额外加入以下语句:

using namespace std;

这是using指令,引入的是命名空间std。
命名空间是一个用于简化大型程序编写和整合多来源前置代码的C++特性。多来源前置代码会导致的问题是两个不同的头文件中可能会存在两个相同名字的对象或方法。比如:

#include <hongkong>
#include <shandong>

int main()
{
	tony();
}

如果hongkong头文件中定义了tony方法,shandong头文件也定义了tony方法。那么编译器在编译以上程序时就没法分辨main方法中调用的tony是哪个头文件中定义的方法。这时就需要命名空间这个概念出手。命名空间机制要求hongkong和shandong都把自己定义的东西放到自己的命名空间内,然后程序就可以使用命名空间来标识被调用的方法的来源。比如:

#include <hongkong>
#include <shandong>

int main()
{
	hongkong::tony();
}

这样编译器就知道main方法调用的是hongkong头文件定义的tony方法。同样的,上面的第一个C++程序可以写成:

#include <iostream>
int main()
{
	std::cout << "hello.";//std是iostream的命名空间的名字
	std::cout << endl;
	return 0;
}

但是每个cout都要标上std挺麻烦的。所以程序可以用using语句将一个命名空间中的所有方法和对象都引入到程序中。一句using namespace std,下面的所有cout就都不需要标识了。
但是这种一刀切的方法其实和命名空间的目的是背离的,在大型程序中可能会导致潜在问题,所以using指令可以仅引入头文件中的单个对象或方法:

using hongkong::tony;
using std::cout;

关于using指令会在第九章更详细地进行讨论。

cout

cout << "hello.";
cout << endl;

最左是cout对象,中间是操作符,最右是要输出的字符串。
endl则是一个特别的C++标识符,意为endline,也即是结束该行。这种对cout有特别意义的称作manipulator(操作符),都在iostream中定义。
当然换行方式不止一种,还有一种是使用"\n"换行符。

cout << "hello.\n";

C++源码格式

有些语言是基于行的,比如FORTRAN。它们是靠换行符分隔语句的。一行就是一句代码。但C++是用分号";"来分隔语句的,也就是说,C++的一句代码是可以任意换行的。比如第一个C++程序可以写成如下样子:

#include <iostream>
int 
	main
()
{
	using
	namespace 
std;
		std::
cout <<        "hello.";
	std::cout          << endl;return 0;
}

但这很明显是反人类的。这样的代码莫说别人读不懂,代码作者过一段时间自己也会难以读懂。所以写代码需要遵循一定的格式才能更合理高效。
另外,C++代码也不是可以随意换行的,在单个元素(比如名字,关键字,字符串)的中间是不能换行或者加空格的。比如:

#include <iostream>
int main()
{
	using namespace std;
	cout << "hel
	lo.";//字符串换行不行
	co  ut << endl;//对象名字中间加空格不行
	return 0;
}

token和空格

token是一个不可分割的概念。两个token之间必须用空格或tab或回车分开。空格,tab和回车同城空白区(white space)。单字符的token(比如括号和逗号)不需要空白区分隔。具体示例如下:

return0;//不行,return和0没分开
return(0);//可以,括号是单字符token,可以省略空白区
return (0);//可以
intmain();//不行,int和main没有分隔
int main();//可以,括号不需要分隔

C++代码样式

理论上C++代码怎么写都是无所谓的,但是如前言提到的,遵循一定格式编写代码效率会更高。比如:

  • 一句一行
  • 标识方法的开始与结束的大括号都各占一行
  • 方法里的语句不要和大括号粘在一起
  • 方法名和小括号之间不要加空白区

前三条是为了代码的干净和可读性。第四条是为了将方法和其他带有小括号的C++结构(比如循环)区分。

C++语句

C++程序是方法的集合,方法是语句的集合。

#include <iostream>

int main()
{
	using namespace std;
	
	int carrots;
	
	carrots = 25;
	cout << "I have " << carrots << " carrots.";
	return 0;
}

以上程序使用了两种新的语句:声明和赋值语句。另外还有cout的新用法。接下来逐条介绍一下这些语句。
(另外提一句,上方程序用空行将声明语句与其他语句隔开了,这其实是C语言的习惯,在C++不常见。不过这都是习惯问题,不重要。)

声明语句

int carrots;

左边是声明的变量的类型,右边是变量的名字,最后分号结束。
额外说一下,为什么要标明变量的类型呢?在其他的语言比如Python,是可以只声明变量名字而省略变量的类型。但这有个潜在问题是这会使声明语句和赋值语句变得无法分辨,从而提高代码维护难度。比如:

DarkFantasy = 1
...
DrakFantasy = 2

假设程序原本是想在第二句将DarkFantasy赋值为2.但因为拼写错误,第二句实际上是声明了一个新的变量DrakFantasy并赋值为2.这就会导致程序出现bug并且由于这里没有语法错误,程序员很难发现这里的拼写错误。

赋值语句

carrots = 25;

左边是被赋值的变量的名字,中间是赋值符号"=",右边是要赋值的值25.
一个不太常用的C++特性是程序可以连续地使用等号:

jack = david = mike = 6;

这一句是从右到左执行的,先将6赋值给mike,再把mike的值赋值给david,再把david的值赋值给jack。也就是上方语句等价于:

mike = 6;
david = mike;
jack = david;

cout新用法

cout << carrots;

这一句向cout传入了carrots这个变量。程序不会输出carrots这个词,而会输出变量的值。这里面其实分为两步。首先cout用carrots的值,比如25,替代carrots。然后,它再将25这个值转换成正确的输出符号。

也就是说,cout既能输出字符串也能输出数字。这听上去好像不怎么厉害,但实际上字符串“25”和数字25是不太一样的。对于这个字符串,程序是存储了‘2’这个字符和‘5’这个字符。但对于数字,程序则是存储了25这个值。所以从数字到字符串,是要经过翻译转换的。

更多的C++语句

cin

cin >> carrots;

这个语句将键盘输入的值赋值给carrots。左边是cin对象(同样也是iostream中定义的对象),中间是操作符,右边是被赋值的变量的名字。C++将程序的输出看做从程序流出的字符流,而输入则是流入程序的字符流。iostream将cin和cout定义为输入输出的象征。就像cout可以将数值转为字符输出一样,cin可以将接收的字符转为数值然后赋值给变量。

用cout进行连接

在上上段程序中就出现了用cout进行连续输出:

cout << "I have " << carrots << " carrots." << endl;

这一句其实等价于:

cout << "I have ";
cout << carrots;
cout << " carrots.";
cout << endl;

甚至,因为C++中空格和回车同样是用于分隔token的空白区,所以还可以采用如下写法:

cout << "I have "
	 << carrots
	 << " carrots."
	 << endl;

cin与cout,类的初识

cin和cout其实就是类。类是OOP(object-oriented-programming,面向对象编程)的核心概念。简单来说类是用户定义的一个数据类型。要定义一个类,要描述它包含的数据以及可以对数据进行的操作。对象是类的一个实例。

方法

方法是C++程序的基础并且是OOP变成的重要概念,所以程序与必须对方法这个概念尽可能熟悉。不过关于方法的许多内容是比较进阶的内容,要等到第七第八章才会讲到。现在先看看方法的一些基础特性。
C++方法分两种,有返回值的和没有的。你可以在标准C++库里找例子,也可以自己写几个。

有返回值的

有返回值的方法可以用来给变量赋值,或者用到别的什么表达式了。比如C和C++的库里都有一个方法叫sqrt,这个方法会返回传入的值的平方根。

x = sqrt(9);

这一句向sqrt方法传入了参数9,方法返回了9的平方根,然后程序将sqrt的返回值赋值给x。这个表达式称作方法调用(function call),sqrt是被调用方法(called function),而包含这个调用语句的方法叫做发起调用方法(calling function)。
括号里的9是传入到方法的参数(argument or parameter)。sqrt接收这个参数,算出平方根,然后返回到发起调用方法。
这就是调用语句的全部。另外要提到就是在调用发起之前,编译器要知道这个方法需要传入的参数的类型和个数以及返回值的类型,以便检查程序有没有错误。所以需要引入方法原型(function prototype statement)。
方法原型语句格式如下:

double sqrt(double)

方法详情

有些方法需要很多的参数,这些参数用逗号分隔:

double add(int, int);

也有些方法不要参数:

int main(void);

和其他语言不一样的是,C++里方法即便不要参数,也要把括号写上。
还有些方法是没有返回值的,这时就又用到void关键字:

void show(int);

没有返回值的方法就不能用于赋值了。

用户自定义方法

标准C++库提供了超过140种预定义的方法,写程序时有合用的就用。但很多时候并不能找到合用的方法,这时就需要自定义方法。每个C++程序都必须有的main方法就是一个自定义方法。

方法格式

声明方法的基本格式如下:

type function_name(argument_list)
{
	statements
}

要注意的是C++和C一样而和Pascal不同,C++不允许在一个方法定义中定义另一个方法。每个方法要平等独立地被声明。

在多方法程序中使用using指令

先前提到using指令引入命名空间。在多方法程序中,可以将using放在方法体外,让引入的命名空间对后续所有方法都可用。也可以将指令放在方法定义内,让引入的命名空间只对该方法有效。
总结一下using指令用法:

  1. 放在方法体外,命名空间对后续所有方法可用;
  2. 方法某个方法定义内,命名空间仅对该方法可用;
  3. 使用类似using std::cout的方式引入明明空间内单个对象
  4. 不使用using指令,在每个对象前加上对应命名空间的名字。比如std::cout << “hello.”;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值