C++语言简介
C++语言的发展简史
C++是由贝尔实验室1979年在C语言的基础上开发成功的。C++兼容C语言,用C语言写的程序基本上可以不加修改地用于C++
C++对C的“增强”表现在两个方面:
(1)在原来面向过程的机制基础上,增强了C语言对类型的处理。
(2)增加了面向对象的机制。
C++语言是一种编译式的、通用的、大小写敏感的编程语言,完全支持面向对象的开发模式。
C++语言的特点
一、基本的输入/输出
在C语言中,标准的键盘输入和屏幕输出功能分别使用scanf()和printf()两个函数实现。
在C++语言中,类库中提供了输入流类istream和输出流类ostream。cin和cout分别是istream类和ostream类的对象,用来实现基本的键盘输入和屏幕输出。
说明:
①标准输入:cin>>变量1>>变量2>>…>>变量n;
②标准输出:cout<<表达式1<<表达式2<<…<<表达式n;
③使用标准输入cin及标准输出cout前,要在程序的最前
面包含:
#include <iostream> //包含头文件:输入输出流
using namespace std;//使用命名空间
④换行操作:用语句cout<<endl;或cout<< “\n”;
⑤当连续从键盘读取想要的数据时,以空格、制表符〈Tab〉键或〈Enter〉键作为分隔符。如果第一个字符是空格、〈Tab〉键或〈Enter〉键,则cin会将其忽略并清除掉,继续读取下一个字符。
⑥用户自己定义的类型的数据,不能直接用“>>”和“<<”进入输入/输出,必须对“>>”和“<<”进行运算符重载后才可以使用。
二、头文件和命名空间
头文件
前面例题中#include <iostream>
每个C++程序由头文件和定义文件组成。头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明,而定义文件用于保存程序的实现。
头文件是用户应用程序和函数库之间的桥梁和纽带。编译时,编译器通过头文件找到对应的函数库,进而把已引用函数的实际内容导出来代替原有函数,然后再进行翻译。
常用的头文件:
标准输入输出流:<iostream>
标准文件流:<fstream>
标准字符串处理函数:<string>
标准数学函数:<cmath>
除了可以使用系统提供的头文件外,程序员还可以定义自己的头文件。
命名空间
一个大型的程序不同模块中出现的标识符之间有可能发生重名现象,这就会引发错误。C++中为了避免名字定义
冲突,特别引入了“命名空间”的定义,即namespace。命名空间的作用是为了消除同名引起的歧义。
在程序中使用标准程序库中的标识符时,要写语句 using namespace std."
三、强制类型转换运算符
当不同类型的量进行混合算术运算时,系统自动进行合理的类型转换,也可以强制转换类型。
1.将一种数据类型转换成另一种数据类型
stati_cast<类型名>(表达式)
说明: stati_cast----可以省略不写
oneint2=static_cast<int>(oneDouble);
oneint2=int(oneDouble);
oneint2= (int) oneDouble;//圆括号
one int22=oneDouble //自动类型转换
2. const_cast<类型名>(表达式)
功能:将常量指针转化成非常量的指针,并且仍然指问原来的对象;或是将常量引用转换成非常量的引用,并且仍然指向原来的对象。
例:int a=10,*q; const int ca=30;
const int*p=&a; //不能使用常量指针p修改a的值
q=const_cast<int *>(p)//不能q=p
*q=20 //变量a的值变为20,不能形成*p=20
p=&ca;//ca的值不能修改
q=const_cast<int *>(p) //不能q=p
*q=40 //*q的值为40,*p的值变成40
//变量ca的仍然是30
四、函数参数的默认值
C++语言规定,定义函数时,只能为函数最后面的连续若干个参数设置默认值,且在调用处也只能缺省后面的连续若干个实参。
例:判断以下函数声明正确与否 //注意不是定义
void df1(inta=2, double=3.0);//正确
void df2(inta, double=3.0);//正确
void df3(int a=2, double b);
void1(inta,intb=2,intc=3);//正确
void f2(int a=1, int b, int c=3):
void f3(int a=1, int b=2, int c):
C++语言规定,在函数调用处只能缺省后面的连续若干个实参,而且所有缺省的实参必须已经有默认值。
例:函数调用示例
函数声明: void func(int a,int b=2,int c=3)
函数调用: func(1,22,33)
func;//错误
func(10,20);
func(5,,9)://错误
C++语言规定,指定默认值时不仅可以用常数,还可以用任何有定义的表达式作为参数的默认值。
例:假设给出如下的函数及变量声明:
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,MAX(a,b),a-b);
func2(4,9);等价于func2(4,9,a-b);
func2(4,,10);错误
注意:函数参数的默认值可以写在声明函数的地方,也可以写在定义函数的地方,但不能在两个地方都写。
函数声明表示有这么个函数了,函数定义就是具体实现了。
函数声明:
int fun(int a, int b):
函数定义:
int fun(int a, int b)
{ int c:
c=a+b:
return c:}
五、引用和函数参数的传递
1.引用:相当于给变量起了一个别名。别名的地址与引用变量的地址是一样的。程序中使用哪个名字都是允许的。
“引用”的定义格式:
类型名&引用名=同类型的变量名
例: int x=10;
int &a=x; //a就是x的一个引用,可以有多个引用
注意:①对象在引用前必须先初始化;
②声明中符号“&”的位置无关紧要。
如int& a=x;int & a=x;int &a=x;等效
常引用的格式:
const 类型名 &引用名=同类型的变量名;
例:int x=10;
int &a=x;//a就是x的一个普通引用
const int &b=x;//b就是x的一个常引用
a=20;//则x=20,b=20
x=30;//则a=30,b=30
b=40;//错误
注意:不能通过常引用去修改其引用的变量的值(带常字的不能动)
constT&和T&是不同的类型。当声明变量并进行初始化时,同类型之间进行初始化是允许的,不同类型之间进行初始化,有些情况下也是允许的。
2.引用在函数中使用
引用作为函数的参数
在C++中,函数调用时参数的传递有两种方式:传值和传引用。传引用是传递对象的首地址值,形参的改变就意味着实参的改变。
引用作为函数返回值
返回引用的函数原型的格式如下:
数据类型&函数名(参数列表);
六、const与指针共同使用
当 const与指针共同使用时,其书写的位置不同,语句含义也不同。
1)如果唯一的const位于符号*的左侧,表示指针所指数据是常量,数据不能通过本指针改变,但可以通过其他方式进行修改;指针本身是变量,可以指向其他的内存单元。
例:int a1=10,a2=20,*pa1=&a1;
*pa1=30; //正确,a1变成10
const int *pa2=&a2;//pa2所指的是常量,pa2是变量
*pa2=40; //错误
pa2=&a1;//正确
2)如果唯一的const位于符号*的右侧,表示指针本身是常量,不能让该指针指向其他内存地址;指针所指的数据可以通过本指针进行修改。
例:int a1=10,a2=20;
int * const pa2=&a2;//指针变量pa2是常量
pa2=&a1; //错误
*pa2=40; //正确
3)在符号*的左右各有一个const时,表示指针和指针所指数据都是常量,既不能让指针指向其他地址,也不能通过指针修改所指向的内容。
例:int a1=10,a2=20;
const int * const pa1=&a1;//数据和指针都是常量
pa1=&a2; //错误
*pa1=30;//错误
int const * const pa2=&a2;//数据和指针都是常量
pa2=&a1;//错误
*pa2=40;//错误
记住 const的修饰规则: const修饰其左侧的内容;如果 const是本行的第一个标识符,则它修饰其右侧的内容。
const int *pa2=&a2;//pa2所指的是常量
int * const pa2=&a2;//指针变量pa2是常量
const int * const pa1=&a1;//数据和指针都是常量
int const * const pa2=&a2;//数据和指针都是常量
七、内联函数
对于需要频繁调用,且代码量少的函数,可以将其定义为内联函数。编译时,编译程序将整个函数体的代码复制到调用该函数的位置。
定义内联函数的格式如下:
inl ine返回值类型函数名(形参表)
{ 函数体 }
如果函数体中有循环语句和 switch语句则通常不定义为内联函数。
八、函数的重载
函数重载:C++允许为同一个函数定义几个版本,从而使一个函数名具有多种功能,这称为函数重载。只要分别为不同参数编制相应的函数体,就可以实现各自的功能。
例:函数重载的例子1
#include <iostream>
using namespace std;
int max(int,int); //声明2个整型参数的函数原型
int max(int, int, int); //声明3个整型参数的函数原型
实现函数的重载必须满足下列条件之一:
参数表中对应的参数类型不同;
参数表中参数个数不同;
参数表中不同类型参数的次序不同。
注意:
1)两个函数的名字和参数表都是一样的,仅仅是返回值类型不同,则这两个函数不是重载的。
例:错误的重载函数
float add(int, float);
int add(int,float); //错误!
2)函数的参数采用引用的,不能区分函数,则这两个函数不是重载的。
例:错误的重载函数
void print(double);
void print(double &); //错误!
3)函数调用可能会引发二义性,不能采用函数重载。
例:若定义了重载函数Sum(),如下所示:
int Sum(int a, int b, int c =0);
int Sum(int a, int b);
则函数调用语句:Sum(1,2);//调用会产生二义性
4)调用语句中的实参与函数形参的类型不完全匹配,但存在赋值兼容的情况。此时,编译器也可以确定要调用的函数。
例:调用函数时进行必要的类型提升
double bigger(double x, double y)
{if(x>y) return x;
else return;}
int xl=10,yl=20;
float xF=30;yF=40;
double xD=50,yD=60;
cout<<bigger(xl,yF)<<endl;//int与float与自动转换为 double
九、指针和动态内存分配
1.指针:即指针变量,该变量储存的是一个地址,是该指针所指对象的首地址。
int a=100, *pa=&a;
int s[10],ps=s;//指针ps指向数组s的首地址
2.动态内存分配
动态分配内存一般格式为:
指针名=new类型名; //分配
delete 指针名; //释放
当不再使用这个空间时,必须使用 delete释放空间。若使用new运算符动态分配了一个数组,那么释放该数组时,语句如下: delete[]指针。
【例】演示使用nw wdelete和的例子
#include <iostream>
using namespace std;
int main()
{ double *p; //声 double明型指针
p= new double[3]; //分配3个double型数据的存储空间
for(int i=0; i<3; i++); //定义对象i的初值为0
cin >> *(p+i); //将输入数据存入指定地址
for(int j=0; j<3; j++)
cout<<*(p+j)<<" "; //将地址里的内容输出
delete[]p: //释放空间
}
十、用string对象处理字符串
C语言用字符数组来处理字符串,C++提供string数据类型来处理字符串。
1.声明 string对象
例: string str; //声明string对象strl,值为空
string city=Beijing; //声明string对象并初始化
string str22=city; //使用字符串变量进行初始化
char name="C++程序”;
string str3=name; //使用字符数组对string变量进行初始化
string citysf[]={"Beijing", "Shanghai", "Tianjing"}; //声明 string对象数组,每个数组元素都是字符串
cout<<sitys[1]<<endl; //输出Shanghai,数组下标从0开始
cout<<sizeof(citys)/sizeof(string)<<endl; //输出数组元素个数
说明:1)使用 string对象,必须#include<string>;
2)string对象储存的是字符串的首地址,非字符串本身; sizeof(string)在32位的Dev C++中是4,在64位的Dev C++中是8。
2.string对象的操作
string对象可以使用cin和cout进行输入和输出
例: string si,s2;
cin>>s1>>s2;
cout<<sl<<","H<<s2<<endl;
string对象之间可以互相赋值,也可以用字符串常量和字符数组的名字对 string对象进行赋值。
例: string sl,s2="OK”;
sl=China”;
s2=s1;//赋值后s2的内容和si相同
string对象之间可以用">" , ">=" , "==" , "<=" , "<" , "!=" 运算符进行比较。大小的判定标准是按字典序进行的,而且是大小写相关的。
例: bool b;//c++新增了bool类型,该类型只有两个取值1或0,1表示“真”,0表示“假”。
string s1="China", s2="OK";
b=s1>s2; //变量b的值为0
使用运算符"+"对字符串进行连接
例: string sl="China",s2="OK",s3=" ";
s1=s1+s3+s2; //连接后s1的内容 "China OK"
3.string类中的常用成员函数
函数 | 功能 |
const char *c_str() const; | 返回一个指向字符串的指针,字符串内容与本 string串相同,用于将 string转换为 const char* |
int size() const: | 返回当前字符串的大小 |
int length()const; | 返回当前字符串的长度 |
bool empty()const; | 判定当前字符串是否为空 |
size_type find( const char *str, size type index): | 返回str在字符串中第一次出现的位置(从index开始 查找),如果没找到则返回-1 |
size_type find( char ch, size type index); | 返回字符ch在字符串中第一次出现的位置(从index 开始查找),如果没找到则返回-1 |
string &insert(int p,const string &s); | 在p位置插入字符串S |
string &append(const char *s); | 将字符串s连接到当前字符串的结尾处 |
string substr(int pos=0,int n=npos)onst; | 返回从pos开始的n个字符组成的字符串 |
C++语言的程序结构
c++程序以.cpp作为文件扩展名,文件中包含若干个类和若干个函数。
程序中有且仅有一个主函数 main(),程序从主函数的开始处执行,在主函数结束。
程序的结束通常是遇到了以下两种情形之一。
1)在主函数中遇到return语句。
2)执行到主函数最后面的括号}。
主函数中可以调用程序中定义的其他函数,但其他函数不能调用主函数,其他函数直接可以相互调用。
C++程序中注释有以下两种形式。
1)从/*开始,到*/结束,如:/*……*/
2)从//直到行尾,如://…
C++的格式和C一样,都很自由,一行可以写几条语句,但也要注意错落有致,增加可读性。
内容小结
C++语言是一种编译式的、通用的、大小写敏感的编程语言,完全支持面向对象的开发模式。
在C++中,可以使用流提取运算符“>>”从标准输入设备键盘取得数据。使用流插入运算符“<<”向输出设备屏幕输出信息。用户自己定义的类型的数据,不能直接用“>>”和“<<”进入输入/输出,必须对“>>”和“<<”进行运算符重载后才可以使用。
头文件使用#include指令包含在程序中,每条#include指令仅可以包含一个头文件。
命名空间是C++的一种机制,在程序中使用标准程序库中的标识符时,要写语句“using namespace std;"。
当不同类型的量进行混合算术运算时,系统自动进行合理的类型转换,也可以在程序中使用强制类型转换运算符进行转换。
在C++语言中,可以在声明函数时为形参指定默认值,提供默认值时必须按从右至左的顺序提供。当调用有默认参数值的函数时,调用语句中可以不给出对应的实参,相当于以默认值作为参数调用该函数,主调函数的实参与被调函数的形参按从左至右的顺序进行匹配对应。
引用相当于给变量起了一个别名。可以定义常引用。不能通过常引用去修改其引用的变量。 const T &和 T & 是不同的类型。 const的修饰规则是:const修饰其左侧的内容。如果 const是本行的第一个标识符,则它修饰其右侧的内容。
在C++中,函数调用时参数的传递有两种方式:传值和传引用。传值,实际上是传递对象的值。传引用是传递对象的首地址值。
定义内联函数时只需在函数头返回值类型的前面加上关键字 inline。
所谓函数重载,是指在程序的同一范围内声明几个功能类似的同名函数。各函数的参数表不能完全相同。函数名加上参数表称为函数的签名。签名不包括函数返回值。
程序运行期间进行的内存分配称为“动态内存分配”,使用new运算符实现动态内存分配。静态内存分配在编译时就能确定占用内存的大小,而动态内存分配一定是在运行期间确定占用内存的大小。
C+标准模板库中提供了 string数据类型,专门用于处理字符串。string是一个类,有很多成员函数。
C++程序以.cpp作为文件扩展名,程序中必须有且仅有一个主函数main(),这是程序执行的总入口。