宁波IT培训
美国上市IT培训机构
0574-87236644
1、多态的分类:多态分为静态多态和动态多态。
静态多态是编译完之后确定所要完成的工作,如:函数重载和泛型编程
说到动态多态就不得不提动态绑定的条件:一是虚函数,基类中必须有虚函数,在派生类中必须重写虚函数;二是,通过基类类型的指针或引用来调用虚函数。
2、说到重写,顾名思义就是将函数重新写一遍,但是也有要求,必须是一个在基类中的虚函数,那么在派生类中必须重写该函数,重写的函数和基类的函数原型相同,不过有一个特例——协变,是重写的特例,基类中返回值是基类类型的引用或指针,在派生类中,返回值为派生类类型的引用或指针。
3、前面说的虚函数都是在普通的成员函数中定义的,那么,现在我们来看几个特殊的成员函数:
构造函数可以定义成虚函数吗?为什么?
构造函数的作用我们都知道,是创建对象的,而虚函数的调用是通过对象来进行的,这是矛盾的,所以说构造函数不能声明成虚函数。
静态成员函数可以定义成虚函数吗?为什么?
如果定义成静态成员函数,那么在这个函数可以通过类名和域作用符来调用,也就是说,不用创建对象就可以调用。虚表地址的使用必须通过对象的地址才能获取。
析构函数可以定义成虚函数吗?为什么?
如果我们定义一个Base*类型的变量,但是调用的是Derived的构造函数,那么之后清理资源的时候,会出现什么问题呢?
我们会发现,调用析构函数的时候只会调用Base类的析构函数,而不会调用Derived的析构函数,这样就会引起内存泄漏,所以我们将析构函数定义成虚函数,就会解决这个问题。
4、虚表指针——>虚表
之前说静态多态的时候举了两个例子,一个是函数重载,另一个是泛型编程,函数重载我们都清楚,并且还和重定义、重写一起总结过,但是这个泛型编程是什么?
编写与类型无关的逻辑代码,就是泛型编程,而模板就是泛型编程的基础。
模板分为两部份,一部分是模板函数,另一部分是模板类。
首先说一下模板函数,其格式是:
template<typename Param1,typename Param2,…>
2、实例化,当你写一个通用的加法的时候,如果将通用类型写成T,那么在来调用函数的时候,通过实例化类型来达到计算任意类型的数据的目的,如果你将T实例化成int类型的那么结果也会是int的,同样的,如果将结果实例化成float、char等也会有相应类型数据的结果。
在模板函数推衍过程中不会进行隐式的类型转化
3、模板形参
模板形参在模板形参列表中只能出现一次
模板形参可以是类型形参也可以是非类型形参,所有类型形参前面必须加上class或者typename关键字修饰
定义模板函数时,模板形参列表不能为空
模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型或自定义类型
在函数模板的内部不能指定缺省的模板实参
显式指定一个空的模板实参列表,该语法告诉编译器只有模板才能来匹配这个调用,而且所有的模板参数都应该根据实参推演出来
4、模板函数的特化:模板函数虽然很强大,可以将代码写完之后带入类型,然后运算该类型的数据,但是并不是所有的类型都适合。我们写的加法的通用函数模板不是不能计算字符串吗?那么该如何解决呢?当然是模板函数的特化了,模板函数特化形式如下:
1.关键字template后面接一对空的尖括号<>
5、模板类
在使用类模板时,需要我们显示的给出模板实参列表,否则编译器无法得知实际的类型。
类模板的成员函数可以在类模板的定义中定义(inline函数),也可以在类模板定义之外定义(此时成员函数定义前面必须加上template及模板参数)。
类模板成员函数本身也是一个模板,类模板被实例化时它并不自动被实例化,只有当它被调用或取地址,才被实例化。
1、C语言异常处理的几种方式:
1.终止程序(除数为0)
2、按类型捕获:异常是通过抛出对象引发的,该对象的类型决定该激活哪一个处理代码。被选中的处理代码是调用链中与该类型匹配且离抛出 对象最近的那一个
抛出异常后会释放局部存储对象,所以被抛出的对象也就还给系统了,throw表达式会初始化一个抛出特殊的异常对象副本(匿名对象),异常对象由编译管理,异常对象在传给对应的catch处理之后撤销。
3、栈展开:栈展开就是沿着调用链查找匹配的catch语句的过程。
刨出异常的时候将暂停当前函数的执行,开始查找匹配的catch子句。首先查找throw本身是否在try块内部如果是再查找匹配的catch子句;如果有匹配的则处理,没有则推出当前函数栈,继续在函数的栈中进行查找。不断重复上述的过程。如果到main函数的栈,还没有找到,那么终止程序。
4、有时候一个catch子句不能处理一个异常,这时候,就会将这个异常重新抛出,交给更外层的调用链处理
5、异常规范
异常对象的类型与catch说明符的类型必须完全匹配。只有以下几种情况例外
不要再构造函数和析构函数中抛出异常,否则可能会引起对像的不完整,导致资源泄露。
说到智能指针我们就会想到几个:auto_ptr、scoped_ptr、shared_ptr
1、那么我们今天在来回顾一下这几个智能指针,首先说一下auto_ptr,auto_ptr在库中是建议不要使用的,因为它有问题:
一是,已经转移权限的指针要是再次被使用的时候会出现错误,因为那个指针在转移资源之后就被赋成空指针了,要是再使用,通过解引用的方法来赋值 ,显然是不行的,所以就报错了。
二是,拷贝运算符接受了常量。我们知道临时对象具有常性,(也就是不能改变),如果使用拷贝运算符的时候,将一个临时对象附进去,也就是像例子中的那样,那么就会出错。
2、说到scoped_ptr,就不得不说它的特点,那就是霸道,因为,它不允许别人和他共用一块内存空间,也就是不允许拷贝。那么问题来了,如何防止拷贝:
记得以前我们给出了三种方法,再来看一下吧:
在类中给出赋值运算符的重载和拷贝构造函数的声明,但是,不给出定义;
在类中给出赋值运算符的重载和拷贝构造函数的定义,不过给成私有的;
在类中 只 给出赋值运算符的重载和拷贝构造函数的声明,并且给成私有的。
说实话,这三种方案现在再来看,只有第三种还可行,因为现在再来看的话,前两种漏洞很容易就会看出,第一种,因为是public的,我们可以在类外将这个函数实现了;第二种,不能防友元。
shared_ptr:定制删除器 和 循环引用
免责声明:内容和图片源自网络,版权归原作者所有
模板
返回值类型 函数名(参数列表)
{
……
}
使用方法完全相同,可用于指定函数形参类型、返回值、局部变量和强制类型转换
2.函数名后接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参
3.函数形参表
4.函数体
异常处理
2.返回一个表示错误的值,附加错误码(GetLastError())
3.返回一个合法值,让程序处于某种非法的状态(坑爹的atoi())
4.调用一个预先准备好在出现”错误”的情况下用的函数(回调函数)。
5.暴力解决方式:abort()或者exit()
6.使用goto语句
7.setjmp()和longjmp()组合
1、允许从非const对象到const的转换。
2、允许从派生类型到基类类型的转换。
3、将数组转换为指向数组类型的指针,将函数转换为指向函数类型的指针。
智能指针