【C++】C++进阶

1.C++介绍:
C语言作为结构化和模块化语言适合规模较小的程序,对于大规模的复杂程序,能够高度抽象和建模的C++则更加适合,C++是C语言的加强版,以C语言为基础,并且完全兼容C语言的特性。
在这里插入图片描述
2.C++对C语言的增强语法
2.1.命名空间
2.2.引用
2.3.函数与运算符的重载
2.4.面向对象的特性
2.5.泛型编程
2.6.异常处理
2.7.标准模板库
下面笔者就者7个特性进行详细说明:
3.命名空间
命名空间是C++提供的一种解决不同文件互相调用时符号名字冲突的方法,一个命名空间就是一个作用域,在不同的命名空间下允许相同的名字符号代表不同的实体。
3.1命名空间的定义
在这里插入图片描述
注意:命名空间的声明要在类和函数的外面定义,并且没有分号结束。
3.2.命名空间成员的引用
命名空间名::成员名
如:
1.cpp
#include
using namesapce std;
/*
命名空间的声明方式,我们需要用到命名空间中的什么方法就在{}内加入什么方法的声明,当然直接使用“using namespace A”来声明A命名空间也是可以的,但是这种命名方法会将A命名空间下的所有方法都作声明,包括我们可能没有使用的方法,当工程很大时,这种做法会导致代码臃肿。
/
namespace A {
int add(int a,int b);
}
int add(int a,int b);
int mian(){
int a = 1,b = 1;
/

在很多多人编程的时候,如果各程序员之间不一直进行密切的交流,极容易出现变量名或方法名类名等相同的情况,这样 在;多文档联合编译时,编译器会无法区分同名符号而报错,而命名空间就很好的解决了这种问题,我们为各个文档都定义一个唯一的命名空间,这样即使是相同符号也可以通过命名空间唯一标识了,命名空间的出现极大的改善了多人编程的困处
/
cout << add(a,b)<<" "<<A::add(a,b)<< endl;
return 0;
}
int add(int a,int b){
return(a + b);
}
2.cpp
#include
namespace A {
int add(int a,int b){
return(a + b);
}
}
3.3.命名空间的别名
命名空间是可以另起别命的,别命是已定义的命名空间的可代替的名字,一个命名空间可以有很多个别名,所有的别命和命名空间原名可以互换使用
别命的定义:namespace 别命 = 命名空间原名;
在这里插入图片描述
3.4.命名空间的成员类型
命名空间的成员类型可以是变量、常量、函数、结构体、联合体、枚举、类、嵌套的命名空间
3.5.全局命名空间
在全局作用域中定义的命名空间,大多数命名空间都属于全局命名空间。即自定义的命名空间是全局命名空间的扩张和细分。全局命名空间是隐式声明的,它存在于每一个程序中。
由于全局命名空间是隐含的,它没有名字,所以使用“::成员名字”引用全局命名空间。
3.6.匿名命名空间
匿名命名空间与全局命名空间类似,也没有名字,但是匿名命名空间定义在局部作用域,不能用于多文件编译。
匿名命名空间可以直接使用变量名引用成员。
4.引用
4.1.什么是引用?
引用即别命,是某一个变量或对象的别命,绑定一个引用到一个变量或对象,即引用初始化,之后对引用的操作完全等价于对与其绑定的变量或对象的操作。
4.2.引用的定义
类型 &引用名 = 目标变量名;
需要注意的是:
- &不是求地址运算符,而是起标志作用
- 引用的类型必须和其所绑定的变量类型相同
- 声明应用的同时必须对其初始化,否则系统会报错
- 引用相当于变量或对象的别命,因此不可将已绑定的引用再绑定其他变量或对象,也不可将一个引用绑定另一个引用。
4.3.引用与指针的区别
+占用存储空间上:
-引用占用一个地址空间,本地计算机的一个地址空间是多少位,引用就占多少位的地址空间。
-而指针除了占用一个地址空间外,还占用一个数据空间用于存储其指向的变量或对象的地址。
+在操作上:
-引用声明的同时必须对其初始化,且初始化后引用不可更改,引用不能为空。如:int &a ;是错误的用法,正确的用法应该是:int &a = b;
-指针的声明可以在任何时候初始化,且指针在后续操作中可以变更其指向的变量或对象,指针可以为空。
+存储内容上
-“sizeof引用”得到的是引用所指向的变量或对象的大小
-“sizeof指针”得到的是指针本身的大小
+层级上
-引用只能有一级,引用不可以再指向引用
-指针理论上对级数没有限制
+可以将引用理解为不可更改的指针,即:类型
const 指针变量
4.4.对数组的引用
类型 (&引用名)[数组下标] = 数组名;
如:对int a[3]数组的引用为int (&quote)[3] = a;即将引用名替换成数组名。
这里要注意,“()”是不能省略的,因为如果省略(),则会改变优先级,变成int &(quote[3]) = a;而出现语法错误。
4.5.对指针的引用
类型* &引用名 = 指针名;
如:int* &quote = p;
4.6.引用的作用
引用既可以作为别命使用,还可以作为函数的参数、函数的返回值使用。
需要注意的是,引用作为函数的返回值时不能返回局部变量的引用。
至此,我可能提出这样的疑问:引用能做的事指针也能做,引用不能做的事指针还能做,那么C++么什么要引入“引用”这个概念呢?
这是因为,指针的操作太过于强大,正因如此对指针的使用存在一定的风险,所谓“收益与风险并存”,在很多高版本的编译器中已经不能再操作指针了,如VS2015,而C++之所以还保留着指针,是因为指针的魅力无比诱人,尽管有风险却不愿意就此抛弃。
引用的另一个用处我们举一个例子来说明
如:
int add_1(int b){
b++;
}
int add_2(int &c){
c++;
}
void mian(){
int a = 1;
int &a = a;
cout<<add_1(a)<<endl;
cout<<add_2(&a)<<endl;
}
我们的输出结果是:1 2,为什么呢?因为普通的参数传递,传递的是参数的拷贝,如add_1我们对b++,实际进行运算的是形参b,而实参a却没有发生运算,所以cout<<add_1(a)输出1,而如果传递引用的话,我们在函数add_2中对引用的操作实质上就是对a进行运算,因为&a就是a。
4.7.常引用
const 类型 &引用名 = 目标变量名
常引用可以引用常量也可以引用变量,常引用不允许通过引用对其绑定的变量或对象进行修改。
在这里插入图片描述5.函数重载
5.1.C++重载的实现
从本质上来说,C++之所以能实现函数的重载是因为C++编译器对函数名的处理方法进行了优化,我们来对比一下C语言编译器和C++编译器对函数名的编译
+C语言编译器
对函数 int add(int a);编译后的名字为:add
+C++编译器
对函数int add(int a);编译后的名字为:addi,对int add(int a,float b);编译后的名字为:addij,C++编译器使用函数名和参数类型的共同组合成编译后函数的唯一标识,即可实现函数的重载。
5.2.重载的定义
重载就是在相同的声明域中函数名相同而参数列表不同,通过函数的参数表唯一标识的函数。
5.3.函数的默认参数
C++可以使用默认参数,即在函数声明时为参数提供一个默认值,当函数调用时没有指定这个参数的值时,编译器会自动使用默认值替换。
在这里插入图片描述
需要注意的是,默认参数只能放在声明或定义处,能放在声明处就放在声明处。如果某个参数是默认参数,那么其后的参数也必须都是默认参数,如:int add(int a = 1,int b,int c);编译器将报错,而int add(int a,int b = 1,int c = 2);则不会报错,因为参数在传递的时候是从左到右的,首先使用无默认参数的参数列表,当遇到没有传入实参的形参时开始使用默认参数的参数列表。使用默认参数的情况仅限于用在没有没有重载冲突的函数上,如:重载add函数,int add(){…} int add(int a = 1,int b = 2){…},此时调用add();将调用不带参数的add()函数。
在这里插入图片描述5.4.内联函数
5.4.1.为什么需要内联函数?
在程序执行的过程中,当碰到函数调用时,系统要将程序当前状态保存到栈中,同时跳转到函数代码处执行函数体,此过程需要占用时间和空间,是的程序执行效率低下。当然我们声明一个内联函数只是建议编译器将此函数作为内联函数,但是编译器有自己的判断算法,在编译时编译器会自行判断我们声明的内联函数是否值得变为内联函数,以保证主程序体不会过于臃肿,所以我们声明的内联函数不一定会成为内联函数。
5.4.2.内联函数的定义
inline 返回值类型 函数名(参数列表){函数体;}
5.4.3.内联函数是一种用空间换时间的措施,通常只有较短的函数才定义为内联函数。
6.new和delete运算符
6.1.new运算符的功能是在堆区分配内存,通过new运算符获得的内存空间都处于堆上。delete运算符的功能正好与new相反,delete运算符的功能是释放new运算符的在堆区创建的内存,new运算符与delete运算符最好是配套出现,即使用new运算符创建了内存就一定要用delete运算符在不需要的时候此内存的时候将其释放,为什么呢?因为堆区的内存是不会随着程序结束而释放的,堆区的内存只要在操作系统关闭时才会释放,所以如果不手动释放new运算符在堆区创建的内存,则会造成大量无用数据占据着堆区内存,当堆区内存被占满时这会出现系统无堆区内存可用而出现系统死机。
6.2.new/delete运算符的使用
new <数据类型> (参数)
delete <对象指针>/delete <对象数组指针>
在这里插入图片描述
6.3.那么C++的new/delete与C语言的malloc/free有什么区别呢?
-它们都是动态管理内存的入口
-malloc/free是C/C++标准库函数,而new/delete是C++操作符
-malloc/free只是动态分分配/释放内存空间,而new/delete除了分配内存空间还会调用构造/析构函数进行初始化/清理(清理成员)
-malloc/free需要手动计算类型大小且返回值为void,而new/delete可以自行计算类型大小返回对应类型的指针
-new/delete在底层是调用了malloc/free的。可以认为是C++对malloc/free的封装
-malloc/free申请空间后需要判空,new/delete则不需要
-new直接跟类型,malloc跟字节数。
new/delete和malloc/free的区别是C++企业招聘时特别喜欢考的一项
7.程序的内存空间
7.1.指针的内存操作
-指针不仅可以可以指向变量还可以指向函数
-有new运算符在堆区创建的内存空间由位于栈区的指针确定入口
在这里插入图片描述
说到这,我们有必要了解一下计算机程序的内存结构,供程序运行的内存空间分为:堆区、栈区、.data段、.bss段、.ro段、.txt段,我使用一张图来说明
在这里插入图片描述
8.面向对象编程的特点
在这里插入图片描述
9.C++中的类
9.1.类的定义
在这里插入图片描述
9.2.访问权限
C++为类的成员添加了三种访问权限
-public–公有成员:权限最高,在public修饰下的成员是类的外部接口,可以被类的成员函数和对象直接访问。
-protected–保护成员:权限居中,可以被类的成员函数和其派生类的成员函数直接访问,但不能被类的对象和派生类的对象直接访问。
-private–私有成员:权限最低,只能通过类的成员函数访问。
9.3.类的成员
-成员变量:类的成员变量用以描述一个对象的属性信息,与一般的变量声明相同,但类的成员变量只能在类的声明体中定义,类的成员变量一般在类的构造函数中初始化,但这不是必须的。
-成员函数:用来描述一个对象的行为动作,与一般的函数声明相同,但只能放在类的声明体中声明,成员函数可以在类内实现也可以在类外实现,但在类内实现则形成内联的成员函数,会使类变得冗杂,所以成员函数的实现最好在类外实现,类成员函数可以重载和带默认参数。
9.5.类的成员函数与成员变量的声明与实现
在这里插入图片描述
9.6.struct和class的区别
-C++对struct关键字扩展了其功能,和class的功能几乎等价
-struct的成员默认访问权限是public,而class是private
9.7.this指针
-this指针是一个特殊的指针,指向对象的自身的首地址
-每一个对象的成员函数都有一个this指针,指向调用的对象,如果要引用整个对象则通过*this引用
-this指针仅能在类的内部使用,即只能在类的声明体或成员函数中使用
9.8.static关键字
9.8.1.static修饰的成员变量–静态成员变量
-static修饰的变量存储在静态变量区
-在类中static关键字修饰的变量被此类的所有对象共享,即所有对象共享这一个变量
-static修饰的变量必须在类外初始化,不可以在定义的时候直接初始化
-static修饰的公有成员变量可以直接通过类名来访问,没有staic修饰的成员变量只能通过对象才能访问
在这里插入图片描述
9.8.2.static修饰的成员函数–静态成员函数
-static修饰的成员函数也可以直接通过类名访问
-静态成员函数只能访问静态成员变量
9.8.3.类的静态与非静态部分
-静态部分只属于类,与类一起存放在内存的静态区,被所有对象共享
-非静态部分属于对象,每个对象都有自己的非静态部分,互不影响
-静态部分只能直接访问静态部分,非静态部分可以访问所有部分
那么为什么静态部分只能直接访问静态部分,而非静态部分却可以访问所有部分呢?
那是因为,非静态成员变量/函数是属于对象的,只能通过对象来访问,而静态部分是属于类的,使用静态部分时没有确定对象的存在,所以不能确定静态部分应该访问哪个对象的非静态部分,而静态部分是属于类的,所有对象共享,所以通过对象使用非静态部分时,可以访问静态部分。
思导图:
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值