文章目录
一、C++语音简介
1、C++语言的发展简史
- 将程序设计语言分为低级语言、中级语言和高级语言。机器语言和汇编语言属于低级语言一类,因为它们能够直接操纵计算机的寄存器和内存。
- 机器语言是一种依赖于CPU的指令系统,使用机器指令的二进制代码编写程序,能够直接被计算机识别。
- 汇编语言使用能够代表指令的助记符来编写程序,可以看作是符号化了的机器语言。
- 高级语言是面向用户的语言,很多语言在形式上接近于算术语言和自然语言,程序员编写方便。使用高级语言编写的程序易读且通用性强,但大部分不能直接与硬件打交道,也不能直接在计算机上运行,需要系统软件的支持,如需要编译程序及链接程序将高级语言编译链接为机器指令后才能运行。
- C语言是C++语言的前身,在进一步扩充和完善C语言的基础上得到了C++语言。
2、C++语言的特点
- 它是C语言的继承,尽量兼容C语言,既保持了C语言的简洁和高效,可以像C语言那样进行结构化程序设计,同时也增强了C语言对类型的处理。
- 加入了面向对象的特征,可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
- 与C语言相比,C++语言的优点:
- (1)从程序运行的稳定性来说,C++语言比C语言更安全,它支持过程化编程、面向对象编程和泛型编程。因为能够支持面向对象的开发方式,所以C++语言的应用领域更加广泛。
- (2)C++语言可运行于多种平台上,如Windows、MAC操作系统及UNIX的多种版本。
- (3)C++语言中加入了面向对象的概念,虽然C语言的语法绝大部分都被保留在C++语言中,但C++的程序结构与C语言的程序结构存在很大差别。
- C++语言对C语言做了很多改进,C++语言相对于C语言的最根本的变化是引进了类和对象的概念。
(1)基本的输入输出
功能 | C语言中使用函数 | C++语言中提供类 | C++类中对象 | 运算符 |
---|---|---|---|---|
键盘输入 | scanf() | 输入流类istream | cin | >> |
键盘输出 | printf() | 输出流类ostream | cout | << |
- 在C++中,可以使用流提取运算符“>>”从标准输入设备键盘取得数据。例如,语句“cin>>x;”从键盘获取输入数据并赋给变量x。使用cin可以获得多个来自键盘的输入值。
- cout是一个标准输出流对象,使用流插入运算符“<<”向输出设备屏幕输出信息。
#include <iostream>
#include <string>
using namespace std;
int main()
{
int oneInt1,oneInt2;
char strArray[20];
string str;
double oneDouble;
char oneChar='a';
/** 注:endl:换行
\n :换行(存在于“”之间)
\t :制表符,即一个tab键(存在于“”之间)
**/
cout<<"请输入两个整型值,一个字符,一个字符串和一个浮点值。";
cout<<"\n以空格、Tab键或Enter键分隔"<<endl;
cin>>oneInt1>>oneInt2>>oneChar>>strArray>>oneDouble;
str=strArray;
cout<<"两个整型值分别是:\t"<<oneInt1<<"和\t"<<oneInt2<<endl;
cout<<"字符是:\t"<<oneChar<<endl;
cout<<"字符串是:\t"<<str<<endl;
cout<<"浮点值是:\t"<<oneDouble<<endl;
return 0;
}
(2)头文件和命名空间
- iostream是C++的标准输入/输出流。当在程序中使用cin或cout时,必须在程序的最前面包含这个流。如果还要使用其他的内容,那么需要包含其他的头文件。每条#include指令仅可以包含一个头文件,如果需要包含多个头文件,则需要使用多条#include指令。【嵌入指令】
- 在C++中,头文件不再以“.h”结尾,以“.h”结尾的头文件是C语言中常用的头文件。
- 常用的头文件有以下一些:
- 标准输入输出流:< iostream >
- 标准文件流:< fstream >
- 标准字符串处理函数:< string >
- 标准数学函数:< cmath >
- 当使用尖括号时,C++编译器将首先在C++系统设定的目录中寻找要包含的文件,如果没有找到,再到指令中指定的目录中去查找。
- 采用双引号时,C++编译器在用户当前目录下或指令中指定的目录下寻找要包含的文件。
例如,要包含e:\myprog目录下的头文件ex1.h,相应的语句如下:
#include "e:\myprog\ex1.h“
- C++中为了避免名字定义冲突,特别引入了“命名空间”的定义,即namespace。命名空间的作用是为了消除同名引起的歧义。 using namespace std;
定义一个命名空间的语法格式如下:
namespace 命名空间名
{
命名空间内的各种声明(函数声明、类声明、……)
}
(3)强制类型转换运算符
/**
static_cast用于将一种数据类型转换成另一种数据类型,使用格式如下:
static_cast<类型名> (表达式)
其功能是把表达式转换为类型名所指定的类型。static_cast也可以省略。
**/
//以程序1-1中声明的变量为例,下面4种写法都是正确的:
oneInt2=static_cast<int>(oneDouble); //强制类型转换
oneInt2=int(oneDouble); //强制类型转换运算符的新形式
oneInt2=(int)oneDouble; //强制类型转换运算符的旧有形式
oneInt2=oneDouble; //自动类型转换
(4)函数参数的默认值
#include <iostream>
using namespace std;
void func(int a=11,int b=22,int c=33) //为参数a,b,c分别设置了默认值11,22与33
{
cout<<"a="<<a<<"\t b="<<b<<"\t c="<<c<<endl;
}
int main()
{
func(); //调用时缺少了3个实参,将使用定义中的3个参数默认值
func(55); //调用时缺少了后2个实参,将使用定义中的后2个参数默认值
func(77,99); //调用时缺少了最后1个实参,将使用定义中的最后1个参数默认值
func(8,88,888); //调用时实参完备,将不使用定义中的任何参数默认值
return 0;
}
C++语言规定,提供默认值时必须按从右至左的顺序提供,即有默认值的形参必须在形参列表的最后。如果有某个形参没有默认值,则它左侧的所有形参都不能有默认值。
调用函数时,主调函数的实参与被调函数的形参按从左至右的顺序进行匹配对应。
(5)引用和函数参数的传递
①引用的定义
- 引用相当于给变量起了一个别名。变量对应于某个内存地址,如果给某个变量起了别名(不需要给它另开辟内存单元),相当于变量和这个引用都对应到同一地址。程序中使用哪个名字都是允许的。
- 在C++中,“引用”的定义格式如下:
- 类型名 &引用名 = 同类型的某变量名;
- 举例如下:
- int oneInt;
- int &name=oneInt; //声明引用
#include <iostream>
using namespace std;
int main()
{
int oneInt=1;
int &refOneInt = oneInt; //refOneInt是oneInt的引用,refOneInt等价于oneInt
const int &constRefOneInt = oneInt; //定义常引用
cout<<"oneInt="<<oneInt<<",\t refOneInt="<<refOneInt<<",\t constRefOneInt="<<constRefOneInt<<endl;
oneInt = 2; //修改oneInt也即修改了refOneInt、constRefOneInt
cout<<"oneInt="<<oneInt<<",\t refOneInt="<<refOneInt<<",\t constRefOneInt="<<constRefOneInt<<endl;
refOneInt = 3; //修改refOneInt也即修改了oneInt、constRefOneInt
cout<<"oneInt="<<oneInt<<",\t refOneInt="<<refOneInt<<",\t constRefOneInt="<<constRefOneInt<<endl;
//constRefOneInt=4 //错误,不能使用常引用对所引用的变量进行修改
int &refOneInt2=refOneInt; //refOneInt2和refOneInt都是oneInt的引用
cout<<"refOneInt2="<<refOneInt2<<endl;
return 0;
}
②引用在函数中的使用
- 在程序中不仅能定义变量的引用,还可以将引用用在函数中。引用既可以作为函数的参数使用,也可以作为函数的返回值使用。
- 在C++中,函数调用时参数的传递有两种方式:传值和传引用。
- 传值,实际上是传递对象的值。
- 传引用是传递对象的首地址值。
- 如果函数的形参不是引用,那么调用时实参传递给形参通常采用的是传值的方式,即将实参的值拷贝给形参。在函数执行过程中,都是对这个拷贝进行操作的,函数执行完毕返回后,形参的值并不拷贝回实参,也就是说函数内部对形参的改变不会影响到函数外实参的值。
- 如果函数的形参是引用,则调用时实参传递给形参采用的是传引用的方式。函数调用时,实参对象名传递给形参对象名,形参对象名就成为实参对象名的别名,即形参是对应实参的引用,它们是等价的,代表同一个对象,也可以看作是将实参的地址传递给了形参。在函数内部对形参的操作,都是对这个地址的内容进行的,相当于对实参的值进行了操作。所以当函数执行完毕返回后,实参的变化被保留下来。
#include <iostream>
using namespace std;
void swapValue(int a,int b)
{
int c = a;
a = b;
b = c;
cout<<"在swapValue()函数中,a="<<a<<"\t b="<<b<<endl;
}
void refSwapValue(int &a,int &b)
{
int c =a;
a = b;
b = c;
cout<<"在refSwapValue()函数中,a="<<a<<"\t b="<<b<<endl;
}
int main()
{
int a=10;
int b=20;
cout<<"执行前,a="<<a<<"\t b="<<b<<endl;
swapValue(a,b);
cout<<"执行后,a="<<a<<"\t b="<<b<<endl;
a=10;b=20;
cout<<"执行前,a="<<a<<"\t b="<<b<<endl;
refSwapValue(a,b);
cout<<"执行后,a="<<a<<"\t b="<<b<<endl;
}
(6)const与指针共同使用
- const修饰指针变量时,基本含义如下:
- 如果唯一的const位于符号*的左侧,表示指针所指数据是常量,数据不能通过本指针改变,但可以通过其他方式进行修改;指针本身是变量,可以指向其他的内存单元。
- 如果唯一的const位于符号*的右侧,表示指针本身是常量,不能让该指针指向其他内存地址;指针所指的数据可以通过本指针进行修改。
- 在符号*的左右各有一个const时,表示指针和指针所指数据都是常量,既不能让指针指向其他地址,也不能通过指针修改所指向的内容。
#include <iostream>
using namespace std;
int main()
{
int a1=3; //普通变量,a1=5是正确的
const int a2=a1;//数据是常量的,a2=5是错误的
int *a3=&a1; //普通指针指向普通变量,*a3=5是正确的
const int *a4 = &a1;//const在*左侧:数据是常量的,不可修改数据,*a4=5是错误的
int *const a5 = &a1;//const在*右侧,指针是常量的,不可修改指针,*a5=5是正确的
//const在*左右两侧,数据、指针均为常量:
//写法一:
int const * const a6 = &a1;
//写法二:
const int * const a7 = &a1;
}
(7)内联函数
- 为了避免这种频繁的函数调用与返回,C++语言引入了内联函数的概念。使用内联函数,编译器在编译时并不生成函数调用,而是将程序中出现的每一个内联函数的调用表达式直接用该内联函数的函数体进行替换,就像整个函数体在调用处被重写了一遍一样。很显然,使用内联函数会使最终可执行程序的体积增大。这是以空间消耗节省时间开销。
- 内联函数应该定义在前,调用在后,定义时只需在函数头返回值类型的前面加上关键字inline。
- 内联函数主要应用于代码量少的函数,频繁调用;
- 如果函数体中有循环语句和switch语句则通常不定义为内联函数。
(8)函数的重载
- 所谓函数重载,是指在程序的同一范围内声明几个功能类似的同名函数。
- 实现函数的重载必须满足下列条件之一:
- 参数表中对应的参数类型不同。
- 参数表中参数个数不同。
- 如果函数参数表中不同类型参数的次序不同,也符合上面所说的条件。要注意的是,返回值类型不能用来区分函数,也就是说,如果两个函数的名字和参数表都是一样的,仅仅是返回值类型不同,则这两个函数不是重载的,编译器认为它们是重复定义,编译时会报错。
(9)指针和动态内存分配
①指针
- 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
// 一般形式:type *var-name;
// type 是指针的基类型,它必须是一个有效的 C++ 数据类型
// var-name 是指针变量的名称。
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
#include <iostream>
using namespace std;
int main ()
{
int var = 20; // 实际变量的声明
int *ip; // 指针变量的声明
ip = &var; // 在指针变量中存储 var 的地址
cout << "Value of var variable: ";
cout << var << endl;
// 输出在指针变量中存储的地址
cout << "Address stored in ip variable: ";
cout << ip << endl;
// 访问指针中地址的值
cout << "Value of *ip variable: ";
cout << *ip << endl;
return 0;
}
②动态内存分配
- 在C++语言中,使用new运算符实现动态内存分配。
- 使用new运算符动态申请的内存空间,需要在使用完毕释放。C++提供了delete运算符,用来释放动态分配的内存空间。
int oneInt=6;
int * p=&ontInt;
cout<<*p<<endl;
delete p; //出错,p是引用,不是动态分配的
int * q=new int;
*q=8;
cout<<*q<<endl;
delete q; //正确,q指向动态分配的空间
(10)用string对象处理字符串
- C++标准模板库中提供了string数据类型,专门用于处理字符串。string是一个类,这个类型的变量称为“string对象”。
- 要在程序中使用string对象,必须在程序中包含头文件string,即在程序的最前面,要加上如下语句:#include< string >
- 声明一个string对象,与声明普通变量是类似的,格式如下:string 变量名;
3、C++语言的程序结构
- C++程序以 .cpp 作为文件扩展名,文件中包含若干个类和若干个函数。程序中必须有且仅有一个主函数main(),这是程序执行的总入口。主函数也称为主程序。程序从主函数main()的开始处执行,主函数可以在任何地方出现,按照其控制结构,一直执行到结束。
- C++程序以.cpp作为文件扩展名,文件中包含若干个类和若干个函数。编译(汇编代码) 转化为汇编码,这种文件称为目标文件。后缀为.obj。 链接(二进制机器码)将汇编代码转换为机器码,生成可执行文件。后缀为.exe。
- 程序的结束通常是遇到了以下两种情形之一:
- ① 在主函数中遇到return语句。
- ② 执行到主函数最后面的括号}。
- 主函数中可以调用程序中定义的其他函数,但其他函数不能调用主函数。主函数仅是系统为执行程序时所调用的。
- C++程序中,仍沿用C语言的注释风格,即注释有以下两种形式:
- ① 从 /* 开始,到 */ 结束,这之间的所有内容都视作注释。
- ② 从//直到行尾,都是注释