C++一些重要知识点的个人理解

总算是考完C++了,前前后后为这门课花费了很多的时间和精力,课程里面的知识点也是巨多巨杂,看完PPT的内容,总是后面部分看完前面的就忘差不多了,哭泣…
为了让自己可以及时地掌握一些比较重要的知识点,特地建了个文档,把一些知识点的个人理解放了进去,下面通过博客发出来和大家一起分享。
自己也是初学者,可能有些内容并不准确,还请批评指正,谢谢。

1、关于虚继承的理解

虚继承主要就是为了解决在继承中的二义性问题
何为二义性问题呢?就是当一个类继承两个类的时候,这两个类可能含有相同的属性和方法,在这个类的对象进行访问其中的属性的时候就不知道该访问哪个类的属性或者方法。业绩就会产生歧义。
如果不通过虚继承的方式,那么在调用的时候就需要把具体的类加上域作用符,这样才能知道我在调用的时候使用的是哪个类。
那么虚继承就可以解决这样的一个问题,在中间的那两个类向上继承某个类的时候,我再继承这两个类,在虚继承的背景下,我只会调用一个构造函数,不会造成歧义。

2、关于多态

多态是面向对象 继承、封装、多态几大基本特性的一种,多态把,主要就是有两种形式,一种是重载(静态联编/前期联编),一种就是重要的虚函数(动态联编/后期联编)
两种方式的差异主要就是在编译的时候重载就已经知道会调用哪个重名函数,但是虚函数则不同,它只有当运行的时候才可以明确知道。

3、运算符重载

关于运算符重载,这里主要就是将运算符作为一种函数,而运算符重载的实质实际上就是函数的重载。
而运算符的重载主要就是有两种方式,一种是重载为类的成员函数的形式,这种形式是含有this指针的,我们需要做的就是给出符号右边的定义即可;
另一种就是重载为友元函数,当我们采用这样的重载时需要给出类的左右两边的定义,是的,两边的定义都要给出来才行,这时候才可以有诸如c1 + 27 / 27 + c1这般操作。

这里说明一下在运算符重载中,经常会用到的两种方式,一种是成员函数的重载方式,另一种是友元函数的重载方式,如果重载为成员函数呢,那么默认这个函数是可以进行调用这个类的相关变量的,因为会通过this指针进行,但是重载为友元函数时(常常作为二元运算符使用时)这时候我们的函数说明是在类外进行的,所以我们就不能通过this指针来传参,这时候最好就是申明两个类的对象,通过对象来进行传参。

4、关于虚函数

首先我们要知道的是虚函数也是成员函数的一种。
为什么需要虚函数呢?因为当我们有一个基类还有一个派生类,当基类的指针指向派生的对象的时候,我们是可以通过指针访问基类的数据成员的,但是,我们却不能通过基类的指针访问派生类的成员函数。
为了能够通过基类的 指针/引用 来访问派生类的成员函数,那么这时候虚函数就派上用场了,通过对基类中的同名函数加一个virtual关键字,在派生类中的相同名字的函数就是虚函数,此时不加virtual关键字也不影响了。
这时我们通过在类外定义一个可以通过基类引用访问基类成员函数的函数,当我们把这个函数作用于派生类的同名函数时就不会出错,也可以这样使用。即可以实现一个接口,多种用途的功能了。
注意虚函数的形式必须保持完全一致,如果将参数个数、返回类型等等,有任何一个不一致,那么就不是真正的虚函数,即使写上了virtual关键字,也不会进行动态联编。
当一个父类的指针指向一个子类的对象时,除了会在成员函数的调用上产生问题,也会在对象的析构上产生问题。当使用delete删除基类指针指向的子类动态对象时,调用的是基类的析构函数。所以这时候虚函数就显得很重要了,当把基类的析构函数加上virtual关键字时,那么这个析构函数就变成了虚函数了,当我们再使用delete删除基类指针删除指向的子类对象时,调用的就是子类对象的析构函数。为了方便起见,在需要多态的场合,一般我们是把析构函数直接定义为虚函数,不管有没有用。
内联函数、静态成员函数、构造函数都不能声明为虚函数
指针是C语言的灵魂,而虚函数是C++的灵魂
通过基类的指针和引用配合虚函数才可以构成动态多态,所以最好声明为public,以供指针或者引用调用。可以申明为private和protected,语义上没问题,但是这样就没什么意义了。

5、关于抽象类

抽象类最直观的感受就是他不能够实例化,但是可以说明指向抽象类的指针和引用,这个指针可以指向由抽象类继承过去的派生类对象
包含纯虚函数的类为抽象类,抽象类至少含有一个纯虚函数,那么什么是纯虚函数?纯虚函数是一种特殊的虚函数,在很多情况下我们在基类中不能在虚函数中给与有意义的实现,而把它说明未纯虚函数,把它的实现留给基类的派生类去实现,相当于为派生类提供了一个框架。如纯虚函数:virtual float Area() const = 0; // 纯虚函数
当抽象类的所有成员函数都是纯虚函数时,那么这个类就被称为接口类

6、关于函数模板与模板函数的理解

因为C++一个重要的性质就是多态,也就是代码的重用,但是很多情况下,当我们使用的参数类型不一致的时候,代码也需要根据参数的不同类型进行适应性的修改,否则就会报错,而函数模板就是这种解决同名函数,相同实现代码,但是可以根据参数类型进行动态变化的一种解决方式。
同时呢,函数模板不能直接使用,需要进行实例化之后才可以进行使用,有点类似于类的那种意思。另外,当把函数模板在头文件中进行定义的时候,不能只保留函数模板的头,而把实现放在另一个文件中,因为函数模板本身并不是一个具体的函数,那么在定义头文件的时候用到函数模板就需要将函数模板的整体全部包含进去。
当参数类型不一致的时候可以有两种方式解决:一种是函数模板可以使用多个模板参数,另一种就是重载模板函数。使用多个模板参数,一般是相同的参数类型,但是参数个数不受到具体的限制。而重载模板函数的话就是和前面讲到的重载函数基本类似,也就是说定义好了一个模板,那么这个模板并不是死的,还可以进行重载,使其具有更多的表现形式。
一般来说我们定义函数模板的时候,参数的类型是一样的,但是当函数的参数不一样时,再使用这个函数模板就会出现错误。这是我们需要对函数模板进行适当的修改,比如可以使用两个类型参数的模板,如
template <class T,class D>
T max(T a,D b)
{ return (T)(a>b?a:b);}

当为一个函数参数类型时:
template
T max(T a,T b)
{return a>b?a:b;}
注:定义的类型参数在函数的参数上必行进行体现,少一个或者多一个都是不可以的。
注:在template< class T >和template< typename T>这两种情形中,很容易造成误解,误解的原因就是将T的类型作为class了,但是这样理解就把T作为了一个类似于int t 这样的一种变量,我自己觉得最好的理解就是将两者进行等价处理。即,class = T ,typename = T,这样的话就好理解点。

7、类模板

类模板的话不是一各具体的类,而是一类类,所以可以实现的功能也就更多了。分为类模板体内定义成员函数,和类模板体外定义成员函数。在体外定义成员函数以及在体外生成对象的时候主要把函数的参数形式进行对应上。
诸如:myclass<int,double>obj1(3,7.3) pair< int >obj1;等等

8、关于内联函数

内联函数的一大作用就是提高代码的效率,在编译和使用的时候节省了参数传递的开销,把函数体直接嵌入到函数的内部进行操作。

9、关于重载函数

C语言中是 不允许有相同的函数名的,但是在C++中却是可以的,这主要就是重载在其中的作用,C++的重载最好就是执行相类似的功能,如果利用重载去执行不相同的功能,总是不好的。另外,重载不能仅仅是返回值类型不同构成的重载,至少要是参数的类型、顺序、个数等有一些明显的变化,否则无法构成重载。

10、关于动态内存

我们知道在C/C++中数组在定义的时候就已经确定好数组的大小了,换句话说也就是数组的这个大小是静态的,是不能改变的。但是在程序运行中,我们不知道会占用多少内存时,这种提前设置好的静态内存就会产生开销过大或者开销太小的问题,这时我们需要一种动态的内存分配来解决这样一个问题,那么堆内存就是这样一种动态的内存形式。
C语言中就要就是通过malloc和free函数进行实现,malloc函数执行成功之后返回内存空间的首地址,这时需要一个指针来指向这个内存空间的首地址,因为malloc返回的指针类型是void型的,所以我们需要通过类型转换变成其他的类型。那么当内存分配失败的时候malloc函数返回的是NULL。这里需要注意的是,在使用malloc申请了一定的内存空间后,务必记得要用free来进行内存空间的释放,而free释放的只是那个指针指向的内容,指针本身还是指向原来的位置,我们在free掉指针指向的内容后记得把指针的值置为NULL。
C++中主要就是通过new和delete来实现动态内存的分配和释放。在使用new的时候需要通过一个指针来指向new之后的内存空间,在释放的时候我们通过delete来进行释放,这里delete释放也是有两种形式,一种是释放数据类型的指针,采用delete[]+指针,另一种的形式就是指针使用delete+指针。释放后把指针指向NULL。

11、关于引用

引用在直观上的理解就是给我们要引用的变量起一个别名,对这个引用的操作,实际上就是对被引用的变量本身进行操作,换汤不换药这种感觉。平时我们可能觉得引用没有什么大的用处,但是引用在作为函数参数的时候可以有很好的用处,这个用处就是传递的函数参数不再是原有变量的一个拷贝或者说是一个副本,传递进去的就是变量本身,所以可以简单理解为就是这个变量本身在参与计算和运行。同时需要注意的就是在函数中返回一个引用的时候最好是一个全局变量的引用,避开一个局部变量的引用。
引用和指针的功能作用有点类似,不过指针需要知道变量的地址,之后才能进行对变量的操作。而引用相比较而言就显得比较简单了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值