一、C++语言的发展简史
根据是否可以直接操纵计算机底层硬件,将程序设计语言分为低级语言
、中级语言
和高级语言
。
机器语言和汇编语言都属于低级语言,能够直接操纵计算机的寄存器和内存。
机器语言是使用机器指令的二进制代码编写程序,能够直接被计算机识别。
汇编语言使用能够代表指令的助记符来编写程序,可以看作是符号化了的机器语言。
高级语言是面向用户的语言。C++属于高级语言。
在83年之前被称为带类的C语言。C语言是C++语言的前身。
98年,C++的ANSI/ISO标准被投入使用,并在03年、11年、14年和17年发布了第二版、第三版、第四版和第五版。
二、C++语言的特点
C++语言是一种编译式的、通用的、大小写敏感的编程语言,完全支持面向对象的开发模式。
主要特点是:
- 是C语言的继承,尽量兼容C语言,既保持了C语言的简介和高效,同时也增强了C语言对类型的处理。
2.加入了面向对象的特征。
一)、基本的输入/输出
在C++语言中,类库中提供了输入流类istream和输出流类ostream。
cin和cout分别是istream类和ostream类的对象,用来实现基本的键盘输入和屏幕输出。
从输入流中获取数据的操作称为提取操作,向输出流中添加数据的操作称为插入操作。
在C++中,可以使用流提取运算符“>>"从标准输入设备键盘取得数据。使用流插入运算符"<<"向输出设备屏幕输出信息。
当程序中用到cin和cout时,需要在程序中包含头文件
cin和cout一般格式
cin>>变量1>>变量2>>...>>变量n;
cout<<表达式1<<表达式2<<...<<表达式n;
cin中的变量可以是任何基本类型的变量。以空格、制表符
例如,输出/输出示例程序1-1,
#include //第1行
#include //第2行
using namespace std; //第3行
int main()
{
int oneInt1,oneInt2;
char strArray[20];
string str;
double oneDouble;
char oneChar = 'a';
cout<<"输入两个整型值,一个字符,一个字符串和一个浮点值,";
cout<<"以空格、Tab键或键分隔:"<>oneInt1>>oneInt2>>oneChar>>strArray>>oneDouble;
str = strArray;
cout<<"输入的数据是:"<
如果想将空格、制表符或
如果输出时双引号括起来的字符串太长了,可以在中间添加符号"".
二)、头文件和命名空间
在C++中,头文件不再以".h"结尾。常用的头文件
标准输入输出流:
标准文件流:
标准字符串处理函数:
标准数学函数:
定义一个命名空间的语法格式
namespace 命名空间名
{
命名空间内的各种声明(函数声明、类声明、...)
}
命名空间也称为名字空间。using namespace std;表示使用命名空间std。
引用其他命名空间的标识符的语法格式:
命名空间名::标识符名
例如,如果没有using namespace std;,则需要分别使用全称std::cin、std::cout、std::string和std::endl等来指明命名空间std。
using语句有两种形式:
using 命名空间名::标识符名;
using namespace 命名空间名;
*三)、强制类型转换运算符
static_cast用于将一种数据类型转换成另一种数据类型
static_cast<类型名>(表达式)
以程序1-1为例,下面4种都是正确的
oneInt2 = static_cast(oneDouble); //强制类型转换
oneInt2 = int(oneDouble); //强制类型转换运算符的新形式
oneInt2 = (int)oneDouble; //强制类型转换运算符的旧有形式
oneInt2 = oneDouble; //自动类型转换
const_cast用于去除指针和引用的常量性,但不能去除变量的常量性。
const_cast<类型名>(表达式)
例如,强制类型转换示例程序1-2
#include
using namespace std;
int main()
{
int a = 10;
const int *p = &a; //不能使用常量指针p修改a的值
const int ca = 30; //被const修饰
int *q;
cout<<"a的地址为:\t"<<&a<<"\ta的值为:\t"<(p); //去除p的常量性赋给q,如果写q=p;会报错
*q = 20; //如果写*p=20;是错误的
cout<<"a的地址为:\t"<<&a<<"\ta的值为:\t"<(p); //去除p的常量性赋给q,如果写q=p;会报错
*q = 40; //如果写*p=40;是错误的
cout<<"ca的地址为:\t"<<&ca<<"\tca的值为:\t"<
四)、函数参数的默认值
在C++中,可以在声明函数时为形参指定默认值。当调用有默认值的函数时,调用语句可以不给出对应的实参。
例如,定义带默认值的函数程序1-3
#include
using namespace std;
void func(int a=11,int b=22,int c=33) //为参数a,b,c分别设置了默认值11,22,33
{
cout<<"a="<
C++语言规定,提供默认值时必须按从右至左的顺序提供,即有默认值的形参必须在形参列表的最后。
在调用函数时,主调函数的实参与被调函数的形参按从左至右的顺序进行匹配对应。
例1-1 函数声明示例
void defaultvalue1(int = 2, double = 3.0); //正确
void defaultvalue2(int a, double b = 3.0); //正确
void defaultvalue3(int a = 2, double b); //错误
void func1(int a, int b = 2,int c = 3); //正确
void func2(int a = 1, int b,int c = 3); //错误
void func3(int a = 1, int b = 2,int c); //错误
例1-2 函数调用示例(一)
假设给出如下的函数声明
void func(int a,int b =2,int c = 3);
func(1,22,33);//正确
func(); //错误,参数a没有默认值
func(10,20);//正确
func(5,,9);//错误,给出的实参必须是连续的。
例1-3 函数调用示例(二)
int Max(int m,int n);
int a,b;
void func2(int x,int y = Max(a,b),int z = a - b){...}
func2(4); //正确
func2(4,9); //正确
五)、引用和函数参数的传递
引用相当于给变量起了一个别名。同一个变量的引用可以有多个。引用的定义格式如下
类型名 &引用名 = 同类型的某变量名;
举例如下
int oneInt;
int &aname = oneInt; //声明引用
定义引用时需要进行初始化。
定义引用时,可以在定义的前面加上cosnt关键字,表明该引用是“常引用”。例如:
int oneInt;
const int &cname = oneInt;
常引用与普通引用区别在于:不能通过常引用去修改其引用的变量。
例如,引用的定义与使用 程序1-4
#include
using namespace std;
int main()
{
int oneInt = 1;
int &ref = oneInt; //ref是oneInt的引用,ref等价于oneInt
const int &refc = oneInt; //定义常引用
ref = 2; //修改ref也即修改了oneInt
cout<<"oneInt=" <
例如对引用进行初始化示例 程序1-5
#include
using namespace std;
int main()
{
const int cInt = 30;
int oneInt = 50;
int &ref = oneInt; //T& ←T
const int &rc1 = cInt; //CT& ←CT,CT&表示类型T的常引用
const int &rc2 = oneInt; // CT& ←T
const int &rc3 = ref; //CT& ←T&
int dInt = ref; //T ←T&
int eInt = cInt; // T←CT,CT表示常量类型
int fInt = rc1; // T ←CT&
const int gInt = oneInt; //CT ←T
int &ref1 = ref; //T& ←T&
const int hInt = ref; //CT ←T&
const int jInt = cInt; //CT←CT
const int &mInt = rc1; //CT& ←CT&
const int nInt = rc2; //CT ←CT&
cout<<"OK"<
T表示类型,CT表示常量类型,T&表示T类型的引用,CT&表示类型T的常引用。
在C++中,函数调用时参数的传递有两种方式:传值
和传引用
。
传值,是传递对象的值。传引用是传递对象的首地址值。
程序1-6 不同的参数传递方式
#include
using namespace std;
void SwapValue(int a,int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
cout<<"在SwapValue()函数中:\t\ta="<
返回引用的函数原型的格式如下
数据类型 & 函数名(参数列表);
程序1-7 引用作为函数返回值
#include
using namespace std;
int oneX = 10;
int oneY = 20;
int &refValue(int &x)
{
return x;
}
int main()
{
refValue(oneX) = 30; //返回值是引用,可以作为左值使用
cout<<"oneX="<
函数的返回值还可以是指针,称为指针函数
类型标识符 * 函数名(参数列表);
六)、const与指针共同使用
与C语言一样,C++语言也可以使用const限定访问权限,告诉编译器,它所修饰的量是不能改变的,也就是不能作为左值使用。
使用指针时,涉及的量一个时指针本身;另一个时指针所指向的内容。
const修饰指针变量时,基本含义如下:
1)如果唯一的const位于符号的左侧,表示指针所指数据是常量,数据不能通过本指针改变,但可以通过其他方式进行修改;指针本身是变量,可以指向其他的内存单元。
2)如果唯一的const位于符号的右侧,表示指针本身是常量,不能让该指针指向其他内存地址:指针所指的数据可以通过本指针进行修改。
3)在符号*的左右各有一个const时,表示指针和指针所指数据都是常量,既不能让指针指向其他地址,也不能通过指针修改所指向的内容。
程序1-8 常量说明示例
#include
using namespace std;
int main()
{
int a1 = 3; //普通变量,a1 = 5是正确的
const int a2 = a1; //数据是常量的,a2 = 5是错误的
int *a3 = &a1; //普通指针指向普通变量,*a3 = 6是正确的
const int * a4 = &a1; //数据是常量的,普通指针*a4=5是错误的
int * const a5 = &a1; //指针是常量的,不能修改指针,但*a5 = 10是正确的
int const * const a6 = &a1; //数据是常量的,指针也是常量的
const int * const a7 = &a1; //数据是常量的,指针也是常量的
return 0;
}
const的修饰规则:const修饰其左侧的内容;如果const是本行的第一个标识符,则它修饰其右侧的内容。
七)、内联函数
在C++语言中使用inline关键字来定义内联函数。inline放在函数定义中函数类型之前。
inline 返回值类型 函数名(形参表)
{
函数体
}
内联函数主要应用于代码量较少的函数。
循环语句和switch语句不能声明为内联函数。
八)、函数的重载
所谓函数重载,是指在程序的同一范围内声明几个功能类似的同名函数。
例1-6 求两者中较大值的函数重载
int bigger(int x,int y)
{
if(x>y)return x;
else return y;
}
float bigger(float x,float y)
{
if(x>y)return x;
else return y;
}
double bigger(double x,double y)
{
if(x>y)return x;
else return y;
}
例1-7 求绝对值函数的重载
int abs(int n)
{
return (n < 0?-n:n);
}
float abs(float n)
{
if(f<0)f=-f;
return f;
}
double abs(double d)
{
if(d < 0)return -d;
return d;
}
实现函数的重载必须满足下列条件之一
- 参数表中对应的参数类型不同
- 参数表中参数个数不同。
例1-8 错误的重载函数
float add(int,float); //将整数和浮点数相加,返回浮点数
int add(int,float); //将整数和浮点数相加,返回整数,错误!
例1-9 错误的重载函数
void print(double);
void print(double&);
例1-10 调用重载函数
int xI = 10,yI = 20;
float xF = 30,yF = 40;
double xD = 50,yD = 60;
cout<
例1-11 调用函数时进行必要的类型提升
double bigger(double x,double y)
{
if(x>y)return x;
else return y;
}
int xI = 10,yI = 20;
float xF = 30,yF = 40;
double xD = 50,yD = 60;
cout<
例1-12 调用重载函数时的二义性
int Sum(int a,int b,int c=0);
int Sum(int a,int b);
调用语句
Sum(1,2);
九)、指针和动态内存分配
指针变量中保存的是一个地址,有时也称指针指向一个地址。
在C++语言中,使用new运算符实现动态内存分配。例如
p = new T;
T是任意类型名,p是类型为T*的指针。这种语句会动态分配除一片大小为sizeof(T)字节的内存空间。并将起始地址赋值给指针p。例如
int *p;
p = new int;
*p = 5;
使用new还可以动态分配一个任意大小的数组
p = new T[N];
例1-14 动态分配整形数组
int *pArray; //指向数组的指针
int i = 5;
pArray = new int[i*20]; //分配了100个元素的整型数组
pArray[0] = 20; //数组的第一个值
pArray[99] = 30; //数组的最后一个值
使用new运算符动态申请的内存空间,需要在使用完毕释放。使用delete运算符来释放动态分配的内存空间。
delete 指针;
例1-15 释放指针时出错
int oneInt = 6;
int *p = &oneInt;
cout<<*p<
如果使用new动态分配了一个数组,释放时,
delete []指针;
十)、用string对象处理字符串
专门用来处理字符串。
string是一个类,这个类型的变量称为“string对象”。一个string对象的大小是固定的。
要在程序中使用string大小,必须在程序中包含头文件string
#include
1.声明string对象
string 变量名;
例如
string str1; //声明string对象str1,值为空
string city = "Beijing"; // 声明string对象city,并使用字符串常量进行初始化
string str2 = city; //声明string对象str2,并使用字符串变量进行初始化
cout<<"str1="<
还可以使用字符数组对string变量进行初始化
char name[] = "C++程序";
string s1 = name;
string citys[] = {"Beijing","Shanghai","Tianjin","Chongqing"};
cout<
2. string对象的操作
可以使用cin和cout进行输入和输出。例如
string s1,s2;
cin>>s1>>s2;
cout<
string对象之间可以互相赋值,也可以用字符串常量和字符数组的名字对string对象进行赋值。例如
string s1,s2 = "OK";
s1 = "China";
s2 = s1; //s1和s2表示的字符串不等长,赋值后s2的内容和s1相同
cout<<"s1="<
3. string对象用法示例
例程序1-9 字符串成员函数的使用
#include
#include
using namespace std;
int main()
{
string str; //未初始化,空串
if(str.empty())
cout<<"str is NULL."<<",length="<
程序1-10 字符串成员函数的使用
#include
#include
using namespace std;
int main()
{
string s1 = "C++语言";
string s2 = "程序设计";
string s3 = s1+s2;
string s4;
s4 = s1.append(s2);
if(s3 == s4) cout<<"结果相同"<
三、C++语言的程序结构
C++程序以".cpp"作为文件扩展名。程序中必须有且仅有一个主函数main(),这是程序执行的总入口。
程序的结束通常是遇到以下两种情形之一
- 在主函数中遇到return语句
- 执行到主函数最后面的括号}。
注释有两种
1.从/开始,到/结束。
2.从//开始。