C++第七篇(续)

一、纯虚函数

1.虚函数要求必须实现,但是如果在父类中的虚函数并没有太大的作用时,可以在父类中可以使用纯虚声明,则不用再实现。eg:

class A
{
        virtual void fun() = 0;  //纯虚函数
}

注意:有任意一个纯虚函数存在的类,被称为抽象类,抽象类不能实例化对象.
抽象类被继承时,子类必须重写纯虚函数,不然也是一个抽象类.

2.虚析构

在多态的使用过程中,如果子类对象空间开辟到堆区(使用了new方式),那么父类指针在释放时
无法调用子类的析构代码(delete)。将父类中的析构改为虚析构,则可以解决该问题.

二、C++模板(泛型编程)

1、作用:C++模板提供了一种通用模具,大大提高了代码的复用性.
2、实现方式:将类型参数化

3、模板分类:函数模板、类模板

语法:

template <typename T1> 

1.函数模板

1、函数内部对象的类型在调用函数时才确定. (类型动态化)
2、在函数模板当中:
        template 只能表示以下一个函数是模板.

template <typename T1>
void fun1(T1 a)
{
}

下面所有函数都将不是函数模板了,一个template <typename T1>只管一个函数
void fun2(T1 b) //不是函数模板,需重新定义

函数模板使用:
        自动类型推导:必须推导出一致的数据类型T,才可以使用   eg:

template <typename T>
void fun(T _n1, T _n2) //自动类型推导两个一样类型的T
{
}
char ch = '1';
int n1 = 23;

int n2 = 10;

fun(n1,n2);  // ture
fun(n , ch); // error!

但是如果显示类型调用的话就可以:fun<int>(n1,n2); //true

注意:模板必须要确定出T的数据类型,才可以使用

emplate <typename T>
void fun()
{
}
fun(); //error

与普通函数关系:
        1、普通函数能够进行隐式类型转换:
        2、函数模板的自动类型推导,不能进行隐式转换

eg:

template <typename T1>
T1 SumFun1(T1 _data1, T1 _data2) //函数模板
{   
    return _data1 + _data2;
}

int SumFun2(int _data1, int _data2) //普通函数
{ 
    return _data1 + _data2;
}

char ch1 = 'a';
char ch2 = 'b';
SumFun1(ch1,ch2);//error 可以调用函数模板但是不能算出正确答案(不能隐式转换)
SumFun1<int>(ch1,ch2); //true,显示调用,正确.

SumFun2(ch1,ch2); //true  普通函数可以进行隐式转换

调用规则:

1.如果普通函数与函数模板都存在(同名且参数与普通函数参数类型也相同时),优先调用普通函数
2.可以通过空模板参数列表来强制性调用模板函数. fun<>(a, b);
3.函数模板可以发生重载
4.如果函数模板可以产生更好的匹配,优先调用函数模板. 
普通函数需要类型转换时,函数模板只需要推导,则优先选择函数模板.

2.类模板

类模板表示将类中的 成员属性 模板化(泛型化)

语法:

template <typename T1, typename T2>
class Person
{
public:
   T1   _attri1;
   T2   _attri2;
};

注意:类模板实例化对象时没有自动推导类型方式,所以必须显示类型    eg:

Person<int, int> p1;   //Person是个类

类模板中的泛型类型可以有默认参数, (函数模板也可以有,意义不大,因为有自动推导)

eg:

template <typename T1, typename T2=int>
class Person
{
public:
   T1 _attri1;
   T2 _attri2;
};

类模板成员函数类外实现方法:

template <typename T1, typename T2=int>
class A
{
public:
        A();
};

template <typename T1, typename T2> //必须添加
A<T1, T2>::A()
{
}

  • 注意:类外实现的成员函数,模板不能有默认参数。// T2 = int error
  • 类模板对象作为函数参数:

1.指定传入类型(用的比较多)

eg:

void fun(Data<string, int> &d)  //Data是一个类
{
}

2.参数模板化

template <typename T1, typename T2>   
void fun(Data<T1, T2> &d)
{
}
template <typename T>
void fun(T &d)
{
}

注意:第二个函数模板中的T代表的是第一个函数模板中的Data这个类

3.类模板与继承:

  • 当子类继承的父类是一个类模板时,子类在声明的时候,要指定父类中的类型

  • 如果要灵活指定父类中的T类型,子类也需要实现为类模板.

eg:

#include <iostream>
using namespace std;

template<typename T>
class Base
{
public:
		T num;
};

class Son: public Base<int>
{
public:
		string name;		
};

template<typename T1, typename T2>
class Son1: public Base<T1>
{	
public:
	T2 id;
};

int main()
{
	Son1<int , char>s1; 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值