day11, 前几天在学黑马里的员工管理系统,还得继续学习

C++另一种编程思想 泛型编程 主要利用的技术就是模板

提供两种模板机制 : 函数模板类模板

模板

模板就是建立通用的模具 , 大大提高复用性。

特点:模板不可直接使用 它只是一个框架  模板的通用不是万能的

函数模板

函数模板语法   建立通用函数,其函数返回值类型和形参类型不可以具体制定,用一个虚拟类型代表。

语法 template<typename T>   函数声明或定义

template声明创建模板  typename 表示其后面的符号是一种数据类型 可以用class 代替,老师建议都是用class。T  通用的数据类型 名称可以替换 通常为大写字母。

下面使用函数模板来实现交换两个数字或者字符等不同的类型

#include<iostream>
#include<string>
using namespace std;

template<typename T>
void myswapInt(T &a , T &b)
{
    T temp = a;
    a = b ;
    b = temp;
}
void test01()
{
    int a = 10 ;
    int b = 10;
    myswapInt(a , b); //第一种调用模板方法,自动类型推导
    myswapInt<int>(a , b);//第二种调用方法,显示指定类型
}
int main()
{
    test01();
    system("pause");
    system("cls");
}

前面还学了一个新的排序方式: 选择排序,这个需要好好理解一下,自己试一试敲以下代码

#include<iostream>
#include<string>
using namespace std ;

//创建交换数字的模板
template<typename T>
void myswap(T &a , T&b)
{
    T temp = a ;    
    a = b ;
    b = temp;
}

template<typename T>
void mySort(T arr[] , int len)
{
    for (int i = 0 ; i < len ; i++)
    {
        int max = i;
        for (int j = i+1 ; j < len ; j++)
        {
            if (arr[j] > arr[max])
            {
                myswap(j , max ) ;//交换下标
            }
        }
        if(max != i)
        {
            myswap(arr[max] , arr[i]);
        }
    }
}
//打印数组的 函数模板
template<typename T>
void printinfo( T arr[] , int len)
{
    for (int i = 0 ; i < len ; i++)
    {
        cout << arr[i] ; 
    }
    cout << endl;
}

//实现字母排序,首先有一个chararr[]  从大到小
void test01()
{
    char chararr[] = "badecf";
    int len = sizeof(chararr)/sizeof(chararr[0]);
    mySort(chararr , len);
    printinfo(chararr , len);
}

int main()
{
    test01();
    system("pause");
    return 0 ;
}

想想这个选择排序的一个过程, 首先在外层循环的时候,先记第一个元素的下标的值为最大值,然后进入内层循环,找arr[i+1]的值,并且判断arr[i+1]值是否会大于之前选定的arr[max]值,如果大于,则arr[i+1]为当前最大值 , 需要交换一下max 和 i 的值,然后继续判断循环,这一轮循环结束后就找到了最大值 ,出循环后,需要判断最大值的下标索引max是否和下标索引为i 的值相等,如果不相等,就交换arr[max]和arr[i]的值,那么i位置上就是最大值,i 目前为 0 ,这就是从大到小进行排序。

普通函数与函数模板区别

1、普通函数调用时可发生自动类型转换(隐式类型转换)

2、函数模板调用时,如果利用自动类型推导,不会发生隐式

int myadd01(int a , int b )
{
    return a+b ; 
}

template<class T>
int myadd(T a , T b )
{
    return a + b ;
}

void test01()
{
    int a = 10 ;
    int b = 20 ;
    char c = 'c';
    myadd(a , c) ; // 报错 , 会显示数据类型不一样
    myadd01(a , c) ; 不报错,因为普通函数会发生隐式数据类型转换 会将字符型c转换为int型
    cout << myadd01(a , c) << endl; //输出109  c - 99
    //如果要使用函数模板必须要指定类型方式 , 因为使用自动类型推导函数模板不会发生隐式类型转换
    myadd<int>(a , c ); // 不报错,使用显示指定类型方法
    cout << myadd(a , c) << endl; 
    
}

总结:建议使用显示指定类型的方式调用函数模板 , 因为可以自己确定通用类型T

普通函数与函数模板调用规则

1、如果函数模板和普通函数都可以实现 , 优先调用普通函数

2、可以通过空模板参数列表来强制调用函数模板

3、函数模板也可以发生重载

4、如果函数模板可以产生更好的匹配,优先调用函数模板

void Myprint(int a, int b) // 优先找函数模板,但是只有声明没有实现,所以会报错
{
	cout << "调用的普通函数" << endl;
}

template<typename T>
void Myprint(T a, T b) 
{
	cout << "调用的函数模板" << endl;
}

template<typename T>
void Myprint(T a, T b , T c)
{
	cout << "调用重载的函数模板" << endl;
}


void test01() 
{
	int a = 10;
	int b = 20;
	//Myprint(a, b);
	
	//Myprint<>(a , b);//通过空模板参数列表,强制调用函数模板
	//Myprint<>(a, b, 100);
	//4、如果函数模板可以产生更好的匹配,优先调用函数模板
	char c1 = 'a';
	char c2 = 'b';
	Myprint(c1, c2);
}

总结:既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性

函数模板局限性

模板的通用性并不是万能的,为了解决自定义数据类型的模板 , C++提供了模板重载,可以为特定的类型提供具体化模板。

class Person
{
public:
    Person( string name , int age)
    {
        this->m_name = name ;
        this->m_age = age ; 
    }

    string m_name;
    int m_age ;

};

//对比两个数相等的函数模板
template<class T>
bool mycompare(T a , T b )
{
    if ( a == b )
    {
        return true;
    }
    else
    {
        return false;
    }
}

//所以要自定义数据类型的模板才可以使用
template<> bool mycompare(Person&p1 , Person&p2 )
{
    if(p1.m_name == p2.m_name && p1.m_age == p2.m_age)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//上述定义的函数模板不能用在自定义的函数类型,用于自定义函数类型会报错
void test01()
{
    Person p1("Tom" , 10);
    Person p2("Tom" , 10);
    bool ref = mycompare(p1, p2);// 报错,因为是自定义的数据类型,编译器不知道如何比较

    //当定义完自定义数据类型模板之后便可以使用模板
    bool ref = mycompare(p1, p2);
    if (ref)
    {
        cout << "p1 == p2" << endl;
    } 
    else
    {
        cout << "p1 != p2" << endl;
    }

}

总结 利用具体化模板可以解决自定义类型的通用化 

学习模板并不是为了写模板 而是在STL能够运用系统提供的模板.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值