一、一个简单的C++示例程序
/**
* C++预处理程序语句都以位于首行的"#"开始,预处理语句有3种,分别是宏定义、文件包含和条件编译,下面的预处理是文件包含语句。
* 文件包含语句除了使用尖括号还可以使用#include "filename"这种形式,采用尖括号是引用系统提供的包含文件,采用双引号是引用
* 定义的包含文件,引用自己定义的文件可以指定用户当前的目录,如:#include "e:\c++\test.h"
*/
#include <iostream> //C++标准输入输出的头文件是iostream
/**
* C语言一直使用扩展名".h"标识头文件,新的C++标准引入了新的标准类库头文件载入方式,即省略".h",但这必须使用下述声明命名空间语句。
* 所谓命名空间,是一种将程序库名称封装起来的方法,它提高了程序的性能和可靠性。
*/
using namespace std;//使用命名空间,让命名空间std内的名称曝光
/**
* C++必须要先声明后使用,如果没有声明语句,编译器扫描到"a = result(a,b);"时就会报错
*/
int result(int,int);//自定义函数原型声明,声明时并不需要给出参数名称,只需要给出参数类型即可,当然也可以给出参数名称
/**
* C语言一般使用"#define"定义常量,在C++中建议使用const来代替宏定义,const是放在定义之前的,因此可以进行类型判别,
* 使用const修饰的标识符是一种特殊的常量,称为符号常量。不过C++中依然可以使用宏定义。无参数的宏作为常量,而带参数的宏
* 则可以提供比函数调用更高的效率,但预处理只会进行简单的文本代替,而不会进行语法检查,所以很容易出问题。
*/
const int k = 2;//也可以使用"const int k(2)"这种构造函数方法进行初始化
struct Calculate{
int x,y;
};
//主函数功能:将结构对象的两个域值相加,乘以2再加50
int main(){//如果函数不需要返回值,这里定义时可以不使用int,用void标识,这里函数结尾就不需要使用"return 0"了,否则编译出错
/**
* 定义对象包括为它命名并赋予它数据类型,一般来说,即便初值只用来表示该对象尚未具有真正意义的值,也应将每个对象进行初始化
*/
int a(0), b(50);//使用构造函数初始化,"int a(0)"相当于"int a = 0"
Calculate c;
/**
* C++将数据从一个对象流向另一个对象的流动抽象为流,从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作
*/
cout << "输入两个整数(以空格区分):";//向输出流中插入字符,<<是插入操作符,cout用来处理标准输出,即屏幕输出
cin >> c.x >> c.y;//从输入流中提取字符,>>是提取操作符,cin用来处理标准输入,即键盘输入
a = (c.x + c.y)*k;
a = result(a,b);
cout << "计算结果如下:" << endl;//cout << endl和cout << "\n"都代表换行
cout << "(a.x+a.y)*k + b=" << a;
/**
* 打印结果:
* 输入两个整数(以空格区分):100 20
* 计算结果如下:
* (a.x+a.y)*k + b=290
*/
return 0;//返回0用来表示函数结束
}
int result(int x, int y){
return x + y;
}
二、认识C++面向对象编程特点
1、函数重载
C++允许为同一个函数定义几个版本,从而使一个函数名具有多种功能,这称为函数重载
#include <iostream>
using namespace std;
int max(int,int);//声明2个参数的函数原型
int max(int,int,int);//声明3个参数的函数原型
int main(){
int a,b,c;
cout << "请输入两个整数值(使用空格区分):" << endl;
cin >> a >> b;
int result = max(a,b);
cout << a << "和" << b << "中最大的整数值为:" << result << endl;
cout << "请输入三个整数值(使用空格区分):" << endl;
cin >> a >> b >> c;
int result1 = max(a,b,c);
cout << a << "、" << b << "、" << c << "中最大的整数值为:" << result1 << endl;
/**
* 运行结果:
* 请输入两个整数值(使用空格区分):
* 25 68
* 25和68中最大的整数值为:68
* 请输入三个整数值(使用空格区分):
* 45 85 12
* 45、85、12中最大的整数值为:85
*
*/
return 0;
}
//对两个数求最大值
int max(int x, int y){
return (x>y)?x:y;
}
//对三个数求最大值
int max(int x, int y, int z){
int a = max(x,y);
return (a>z)?a:z;
}
2、新的基本数据类型和注意事项
① void是无类型标识符,只能用来声明函数的返回值类型,不能用来声明变量;
② C++标准限定int和short至少要有16位,而long至少32位,short不得长于int,int不得长于long,int使用4字节;
③ 地址运算符"&"用来获取对象存储的地址,存储地址用16进制表示,例如下:
//声明并定义一个对象,使用"&"来获取对象的存储地址并输出
void example1(){
int x = 50;
cout << &x;//打印结果:0x62ff1c
}
④ C++中的整数常量有四种类型:十进制常量、长整型常量、八进制常量和十六进制常量,并用前缀和后缀进行分类标识
//整数常量示例
void example2(){
//十进制常量 -32768 0 32767 +123 -456 987
//长整型常量(后缀L或l) 123L -457l 0L 1l
//八进制常量(前缀0) 0123 05
//十六进制常量(前缀0x) 0x10 0x1A
}
⑤ 可以用后缀表示浮点常量的类型,带F或f的是float类型;L或l表示它是long double类型;没有后缀则是double类型
//浮点型常量示例
void example3(){
//double型浮点常量 3. 123.4 0.002 52.4
//float型浮点常量 3.2F 4.5f 0.002f
//长浮点常量 0.2L 4.5l
}
3、动态分配内存
在使用指针时,如果不使用对象地址初始化指针,可以自己给它分配地址,如下示例:
void example4(){
const int size = 3;
int *i = new int[size];//声明int型指针并分配3个int型数据的存储空间
cout << "请输入3个整数(以空格区分):" << endl;
for(int t=0;t<size;t++){//循环将输入的数字存入指定的地址
cin >> *(i+t);
}
for(int k=0;k<size;k++){//循环将地址里的内容输出
cout << *(i+k) << " ";
}
delete i;//当不再使用这个空间时,释放空间
}
4、引用
引用就是为现有的对象起一个别名,选定命名时使用“引用”运算符"&",它将一个新标识符与一块已经存在的存储区域相关联,引用并没有分配新的存储区域,它本身并不是新的数据类型。如下简单示例:
void example5(){
int x = 25;//定义并初始化变量x
int &a = x;//声明a是x的引用,此时a和x的地址相同
cout << "x的值是:" << x << ",变量x的内存地址是:" << &x << ",引用a的值是:" << a
<< ",引用a的内存地址是:" << &a << endl;
a = 30;//改变引用a的值,同时就改变了该内存地址中的值
cout << "x的值是:" << x << ",变量x的内存地址是:" << &x << ",引用a的值是:" << a
<< ",引用a的内存地址是:" << &a << endl;
/**
* 打印结果:
* x的值是:25,变量x的内存地址是:0x62ff18,引用a的值是:25,引用a的内存地址是:0x62ff18
* x的值是:30,变量x的内存地址是:0x62ff18,引用a的值是:30,引用a的内存地址是:0x62ff18
*/
}
理解引用的两点:
① 引用实际上就是变量的别名,它同变量在使用形式上是完全一样的,它只作为一种标识对象的手段。不能直接声明对数组的引用,不能声明引用的引用,可以声明对指针的引用,也可以声明指向引用的指针。
② 引用与指针有相似之处,它可以对内存地址上存在的变量进行修改,但它不占用新的地址,从而节省开销。指针是低级的直接操作内存地址的机制,指针功能强大但极易产生错误;引用则是较高级的封装了指针的特性,它并不直接操作内存地址,不可以由强制类型转换而得,因而具有较高的安全性。
如何建立对数组的引用,可以通过typedef来实现,如下示例:
void example6(){
const int size = 5;//声明const常量
typedef int array[size];//定义一个int型的数组标识符array
array a = {10,20,30,40,50};//对数组进行初始化
array &b = a;//引用数组a
a[1] = 100;//改变数组a中的值
for(int i = 0;i<size;i++){//循环数组b,数组b中的值也会跟着同步
cout << *(b+i) << " ";//10 100 30 40 50
}
}
5、对指针使用const限定符
① 指向常量的指针
指向常量的指针是在非常量指针前面使用const,例如:const int *p; 它告诉编译器"*p"是常量,不能将"*p"作为左值来操作,如下:
const int y = 50;
const int *p = &y;//指向常量的指针指向y,y是常量,不可以作为左值
再比如:
int x = 20;
const int *p = &x;//这时"*p"不能作为左值,但可以使用"x="来改变x的值,所以这个const仅仅是限定了使用"*p"的方式
② 常量指针
把const限定符放在*号的右边,使指针本身成为一个const指针,如下:
int x = 5;
int * const p = &x;//这个指针本身就是常量,编译器要求给它一个初始值,这个值在整个指针的生存周期都不会改变,但可以使用"*p="来改变其值
③ 指向常量的常量指针
例如:
int x = 2;
const int * const p = &x;//这时告诉编译器*p和p都是常量,限制了"&"和"*"运算符
6、泛型算法应用于普通数组
要输出数组的内容、对数组进行升幂排序、反转数组的内容、复制数组的内容等操作,需要包含头文件<algorithm>
reverse(a,a+length);//数组元素反转排列
copy(a,a+length,b);//将数组a的内容复制到数组b
reverse_copy(a,a+length,b);将数组a的内容以逆向方式复制到数组b
sort(a,a+length);//默认是升幂排序
copy(a,a+length,ostream_iterator<type>(cout,"字符串"));//将数组内容按正向方式输送到屏幕
copy(a,a+length,ostream_iterator<type>(cout," "));//在每个输出元素后面增加一个空格
copy(a,a+length,ostream_iterator<type>(cout,"\n"));//在输出每个元素之后,换行
要对数组进行降幂排序和检索,需要包含头文件<functional>
sort(b,b+length,greater<type>());//数组降幂排序
find(a,a+length,value);//查找数组a内是否存在值为value的元素,它返回的是位置指针
7、数据的简单输入输出格式
C++提供了两种格式控制方式:一种是使用iso_base类提供的接口;另一种是使用一种称为操控符的特殊函数,它的特点是可直接包含在输出和输入表达式中。不带形式参数的操控符定义在头文件<iostream>中,带形式参数的操控符定义在头文件<iomanip>中。
名称 | 含义 | 作用 |
dec | 设置转换基数为十进制 | 输入/输出 |
oct | 设置转换基数为八进制 | 输入/输出 |
hex | 设置转换基数为十六进制 | 输入/输出 |
endl | 输出一个换行符并刷新流 | 输出 |
resetionsflags(long flag) | 清除flag指定的标志位 | 输出 |
setiosflags(long flag) | 设置flag指定的标志位 | 输出 |
setfill(char ch) | 设置ch为填充字符 | 输出 |
setprecision(int n) | 设置浮点数输出精度n | 输出 |
setw(int width) | 设置输出数据字段宽度width | 输出 |
resetiosflags和setiosflags的参数flag是引用C++的类ios_base里定义的枚举常量,所以要使用限定符"::"
常量名 | 含义 |
ios_base::left | 输出数据按输出域左边对齐输出 |
ios_base::right | 输出数据按输出域右边对齐输出 |
ios_base::showpoint | 浮点输出时必须带有一个小数点 |
ios_base::showpos | 在正数前面添加一个"+"号 |
ios_base::scientific | 使用科学计数法表示浮点数 |
ios_base::fixed | 使用定点形式表示浮点数 |
三、程序的编辑、编译和运行的基本概念
用C++语言写成的程序被称为源程序,源程序必须经过C++编译器程序翻译成机器语言才能执行,其大概过程如下:
① 先使用编辑器编辑一个C++源程序my.cpp;
② 然后使用C++编译器对这个源程序进行编译,产生my.obj文件;
③ 再使用连接程序,将my.obj变成my.exe可执行文件。
集成环境:就是将C++语言的编辑、编译、连接、运行程序都集中到一个综合环境中去。