浅谈C++中的泛型编程

本文深入探讨C++中的泛型编程,包括函数模板和类模板的语法格式、使用案例及编译机制。通过实例解析模板函数与普通函数的差异,并讨论模板类的派生。

一、概述

泛型(Generic Programming)即是指具有在多种数据类型上皆可操作的含
意。所谓泛型编程,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。上面所叙述的是函数模板,实际上模板分为函数模板和类模板。类模板与函数模板的定义和使用类似,有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,所以将类中的类型进行泛化。

二、模板的形式

1、函数模板语法格式
template<typenam T>
template<class T>
-------------------------------------
template<typename 类型参数表>
 返回类型 函数模板名(函数参数列表)
{
    函数模板定义体
}
2、类模板的语法格式
template<typename T>
class A{}

template是语义是模板的意思,尖括号中先写关键字 typename 或是
class ,后 面跟一个类型 T,此类即是虚拟的类型。至于为什么用 T,用的人多了,也就是 T 了。

三、函数模板细化和模板案例

1、模板函数小案例
#include <iostream>
using namespace std;

template<typename T>
void swap(T &a, T &b)
{
    T t = a;
    a = b;
    b = t;
}

int main()
{
    int x = 10;
    int y = 20;
    cout << "int型交换前" << endl;
    cout << "x=" << x << "y=" << y << endl; 
    swap<int>(x, y);
    cout << "int型交换后" << endl;
    cout << "x=" << x << "y=" << y << endl; 

    float e = 1.1;
    float f = 2.2;
    cout << "float类型交换前" << endl;
    cout << "e=" << e << "f=" << f << endl; 
    swap <float>(e, f);
    cout << "float类型交换后" << endl;
    cout << "e=" << e << "f=" << f << endl;

    return 0;
}

总结:函数模板,只适用于函数的参数个数相同而类型不同,且函数体相同的情况。如果个数不同,则不能用函数模板

2、函数模板与函数重载
#include <iostream>
using namespace std;
template <typename T>
void swap(T &a, T &b)
{
    cout << "我是模板函数" << endl;
    T t = a;
    a = b;
    b = t;  
}

void swap(char &a, int &b)
{
    cout << "我是普通函数" << endl;
    int t = a;
    a = b;
    b = t;
}

int main()
{
    char cData = "a";
    int iDate = 10;
    swap(cData, iDate);
    swap(iDate, cData);
    swap<int>(iDate, cData);
    return 0;
}

总结:普通函数会进行隐士的数据类型转换, 函数模板不提供隐式的数据类型转换必须是严格的匹配。当函数模板和普通函数都符合调⽤用时,优先选择普通函数,若显⽰示使⽤用函数模板,则使⽤用<>类型列表。如果
函数模板产⽣生更好的匹配使⽤用函数模板。

3、模板编译机制总结
  • 编译器并不是把函数模板处理成能够处理任意类的函数
  • 编译器从函数模板通过具体类型产生不同的函数
  • 编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

四、类模板细化和模板案例

1、一个简单的类模板小案例
#include <iostream>
using namespace std;

template<typename T>
//template<class T>
class A
{
    public:
        A(T tt)
        {
            this->t = tt;   
        }

        T &getT()
        {
            return t;   
        }

    private:
        T t;
};

int main(void)
{
    A<int> a(100);
    cout << a.getT() << endl;
    return 0;
}

总结:在类模板前应该用template<typename T>或者template<class T>来声明。

2、模板类的派生
#include <iostream>
using namespace std;

template<typename T>
class A
{
    public:
        A(T tt)
        {
            this->t = tt;   
        }
    private:
        T t;
};

//模板类派生普通类
class B : public A<int>
{
    public:
        B(int t, int ii) : A<int> a
        {
            this->ii = i;   
        }

        void printB()
        {
            cout<< "i:" << i <<endl;
        }
    private:
        int i;
}

//模板类派生模板类
template <class T>
class C : public A<T>
{
    public:
        C(T jj, T t) : A<T> t
        {
            this->jj = j;   
        }

        void printC()
        {
            cout << "j:" << j <<endl;
        }
    private:
        T j;
};

总结:子类从模板类继承的时候,需要让编译器知道⽗父类的数据类型具体是什么(数据类型的本质:固定⼤大⼩小内存块的别名)A<int>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The_Web3_社区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值