c++模板,特化,仿函数,继承(复习专用)

道歉:前段时间忽略了,我可能比较懒吧(可能周末期来临了,),我要自我反思,希望大家多多督促我,我们一起向前进步

引子1:as we all known ,在c语言中我们进行不同类型时,要用不同函数名以及不同类型修饰,对此c++先引用了函数重载概念,但是这只是解决不同函数名的问题,所以,c++又引入模板来解决不同类型问题,避免重复写的麻烦!

引子2:当我们想在上一个类中进行扩展以及修改时,我们就要使用继承的知识(叫做基于基类的派生类)!

模板:

模板分为函数模板和类模板

关键字:template<typenme T>

typename是用来定义模板参数关键字,也可以使用class

函数模板

函数模板在使用时被参数化,根据实参类型产生函数的特定类型版本

编译器推演原理:在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供 调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然 后产生一份专门处理double类型的代码,对于字符类型也是如此。如下图的调试:

但是要注意的是:让编译器根据实参推演模板参数的实际类型时,通过实参h1将T推演为int,通过实参h2将T推演为double类型,但模板参数列表中只有一个T, 编译器无法确定此处到底该将T确定为int 或者 double类型而报错!

对此,我们要进行强制转化或使用显式实例化,auto也是可以的

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错

模板参数的匹配原则  :找最符合自己胃口的进行使用!(能省力就省力!)

1,对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

2,模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

类模板

类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类,注意不同的类型就是一个新的类!

非类型模板参数

其实也很简单就是,在传的时候加一个常量,注意: 1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。 2. 非类型的模板参数必须在编译期就能确认结果。

用法也很简单:

区别:My_array<int ,10>与int array[10]

越界检查:int array[10]是一种抽查,进行读的时候不会有影响

My_array<int ,10>是一种严格的检查!只要有调用时越界就会抛异常!

强调点:模板是按需实例化的,不实例化,编译器可能不知道类型不敢,就会报错!

要使用(typename 确定类型!);

模板的特化

模板特化中分为函数模板特化与类模板特化

函数模板特化

函数模板的特化步骤: 1. 必须要先有一个基础的函数模板 2. 关键字template后面接一对空的尖括号<> 3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型 4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误!

// 调用特化之后的版本,而不走模板生成了

有一个小坑:注意const指向,如下图

类模板特化

分为全特化和偏特化

全特化即是将模板参数列表中所有的参数都确定化;

注意:也可以是指针,引用,*等类型!

偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。比如对于以下模板类

第一种常见用法:

第二种常见用法:

仿函数

仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

AS:less就是一个仿函数

个人认为这个仿函数有在之定义类型很有意义!尤其在一个类里实现大小排序转换!

template<>

struct LessDate*>

{ bool operator()(Date* x, Date* y) const { return *x *y; } };

继承

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保 持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象 程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继 承是类设计层次的复用。

注意点:1,基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私 有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面 都不能去访问它。2,在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡 使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里 面使用,实际中扩展维护性不强。

基类和派生类对象赋值转换

派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片 或者切割。寓意把派生类中父类那部分切来赋值过去。 基类对象不能赋值给派生类对象!

在c语言中也有相似的,叫截断!

继承中的作用域

1. 在继承体系中基类和派生类都有独立的作用域。 2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏, 也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问) 3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。 4. 注意在实际中在继承体系里面最好不要定义同名的成员

继承中的默认构造函数

   我们下节在见吧!下节我将与题目一起结合起来与大家分享!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值