c++模板

new char(10);申请一个char类型的空间初始化为10
new char[10];申请10各char类型空间
泛型编程:
模板:分为函数模板和类模板
c++提供了函数模板,所谓的函数模板就是一个通用的函数
类型太多了,但是逻辑又非常相似,于是就让类型参数化
 

//1.自动类型推演,让编译器自己进行类型推演,如果有产生二义性直接报错
#include<iostream>
using namespace std;
template <class T>   //告诉编译器下面如果出现T不要报错,T是一个通用类型
void myswap(T &a, T &b)
{
	T temp = a;
	a = b;
	b = temp;
}
int main()
{
    int a = 10;
    int b = 20;
    double c = 3.14;
    double d = 4.23;
    myswap(a, b);
    myswap(c, d);
    cout << a << endl << b << endl;
    cout << c << endl << d << endl;
    return 0;
}
//2.显示指定类型
#include<iostream>
using namespace std;
template <class T>   //告诉编译器下面如果出现T不要报错,T是一个通用类型
void myswap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
int main()
{
    int a = 10;
    int b = 20;
    double c = 3.14;
    double d = 4.23;
    myswap<int>(a, b);
    myswap<double>(c, d);
    cout << a << endl << b << endl;
    cout << c << endl << d << endl;
    return 0;
}

 

模板必须要指定出T才可以使用,不要让编译器去猜,去推倒,一般显示指定就好了,否则容易出错

 

通过类模板实现一个选择排序

#include<iostream>
using namespace std;
template<class T>
void myswap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
template<class T>
void mysort(T array[], int len)
{
    for (int i = 0; i < len; ++i)
    {
	int max = i;
	int j = i + 1;
	for(j; j < len; ++j)
	{
	    if (array[max] < array[j])
	    max = j;
	}
	if (max != i)
	myswap(array[i], array[max]);
    }
}
template<class T>
void printfs(T array[],int len)
{
    for (int i = 0; i < len; ++i)
    {
	cout << array[i]<<" ";
    }
    cout << endl;
}
void test()
{
    char a[] = "helloworld";
    int b[] = { 5, 8, 7, 4, 6, 3, 1, 9, 2, 0 };
    int num = sizeof (a) / sizeof (a[0]);
    mysort(a, num);
    printfs(a, num);
    int num1 = sizeof (b) / sizeof (b[0]);
    mysort(b, num1);
    printfs(b, num1);
}
int main()
{
    test();
    return 0;
}

template<calss T>只能保证紧跟真的那个函数里面的T不报错意思就是,函数要想使用模板就必须每个函数前面都要有一个模板template<calss T>

函数模板与普通函数的区别以及调用规则

区别:模板无法进行隐式类型转换

#include<iostream>
using namespace std;
template<class T>
void plus1(T &a,T &b)
{
    cout << a + b << endl;
}
void plus2(int a, int b)
{
    cout << a + b << endl;
}
int main()
{
    int a = 10;
    int b = 20;
    char c = 'c';
    plus1(a, b);
    //plus(a, c);函数模板不能进行隐士类型转换
    plus2(a, c);
    return 0;
}

函数模板调用规则

#include<iostream>
using namespace std;
template<class T>
void func(T a, T b)
{
    cout << "函数模板调用\n";
}
void func(int a, int b)
{
    cout << "普通函数调用\n";
}
int main()
{
    int a = 10;
    int b = 20;
    func(a, b);
    //结论
    //1.如果出现函数重载,那么优先调用普通函数,就算普通函数只有声明没有定义,报错也优先调用普通函数
    //2.如果想要强制调用函数模板,那么就要用空的参数列表。例如:func<>(a, b);强制调用函数模板
    //3.函数模板也可以发生重载(示例在下面)
    return 0;
}

//3.函数模板也可以发生重载(示例在下面)
#include<iostream>
using namespace std;
template<class T>
void func(T a, T b)
{
    cout << "函数模板调用\n";
}
template<class T>
void func(T a,T b,T c)
{
    cout <<"三参数函数模板调用\n";
}
int main()
{
    int a = 10;
    int b = 20;
    int c = 30;
    func(a, b, c);
    return 0;
}

//4.如果函数模板可以产生更好的匹配那么优先使用函数模板
#include<iostream>
using namespace std;
template<class T>
void func(T a, T b)
{
    cout << "函数模板调用\n";
}
void func(int a, int b)
{
    cout << "普通函数调用\n";
}
int main()
{
    char a = 'a';
    char b = 'b';
    func(a, b);    
    return 0;
}
//此时将调用函数模板,因为不会产生隐式类型转换

 

模板机制

1.模板不是万能的,并不是可以通用所有数据类型

2.通过模板生成的函数叫模板函数

一个模板在被调用的时候就会通过这个模板产生一个函数(参数类型已经赋好好的函数),这个函数就叫做模板函数。

3.操作系统会对模板进行二次编译,第一次是对函数模板进行编译,推演出所有类型之后,再对模板函数进行编译。

 

类模板的基本使用

#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class person
{
public:
    person(T1 a,T2 b)
    {
	this->name = a;
	this->ages = b;
    }
    void printfs()
    {
	cout << this->ages << endl << this->name << endl;
    }
    T1 name;
    T2 ages;
};
void test()
{
    //person p("孙悟空",10);这个是错误的写法因为类模板不支持自动的推演,只支持显示化调用
    person<string, int>p("孙悟空",10);
    p.printfs();
}
int main()
{
    test();
    return 0;
}

还有一点就是类模板可以有默认的参数,函数模板不可以

template<class T1 = int ,class T2 = string>
class person
{

};

 

成员函数的创建时机:一开始并不会去创建 ,只有在运行的时候才会根据模板创建函数

类模板做函数参数:

1.显示传入指定参数

2.参数模板化

3.类整体模板化

#include<iostream>
#include<string>
using namespace std;
template <class T1, class T2>
class person
{
public:
    person(T1 a, T2 b)
    {
	this->name = a;
	this->ages = b;
    }
    void func()
    {
	cout << this->name << endl << this->ages << endl;
    }
    T1 name;    
    T2 ages;    
};
//1.指定传入参数
void funcs(person<string, int> &a)
{
    a.func();
}
//2.参数模板化
template<class T1,class T2>
void funcs2(person<T1,T2>&a)
{
    a.func();
}
void test()
{
    person<string, int>p1("猪八戒", 10);
    funcs(p1);
    person<string, int>p2("呆贼", 18);
    funcs2(p2);
}
int main()
{
    test();
    return 0;
}
#include<iostream>
#include<string>
using namespace std;
template <class T1, class T2>
class person
{
public:
    person(T1 a, T2 b)
    {
	this->name = a;
	this->ages = b;
    }
    void func()
    {
	cout << this->name << endl << this->ages << endl;
    }
    T1 name;
    T2 ages;
};
template<class T>
//3.整体模板化,直接让操作系统对person这个类进行推演
void funcs(T &a)
{
    a.func();
}
void test()
{
    person<string, int>p1("猪八戒", 10);
    funcs(p1);
}
int main()
{
    test();
    return 0;
}

如何查看推导出来的函数类型:(string类型原名很长)

void funcs(T &a)
{
    cout << typeid(T).name() << endl;
    a.func();
}

//结果就是
class person<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int>
猪八戒
10
请按任意键继续. . .

类模板碰到继承的问题以及解决:

#include<iostream>
using namespace std;
template<class T>
class person
{
public:
    T myname;
};
class dog : public person<int>   //1.写死的类型
{

};
template<class T1,class T2>
class dog2 : public person<T2>   //2.用户自定义的类型T2直接就是基类的T类型
{
public:
    T1 myname;
};

类模板的类外实现成员函数:

#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class person
{
public:
    person(T1 name, T2 ages);
    void func();
    T1 name;
    T2 ages;
};
//与普通调用相比在开头多了模板声明
template<class T1,class T2>
person<T1,T2>::person(T1 name, T2 ages)//在指定作用域的时候多了<T1, T2>
{
    this->name = name;
    this->ages = ages;
}
template<class T1,class T2>
void person<T1,T2>::func()
{
    cout << this->name << endl << this->ages << endl;
}
void test()
{
    person<string, int>p1("狗贼", 18);
    p1.func();
}
int main()
{
    test();
    return 0;
}

 

要是报无法解析的外部命令一般都是在链接的时候找不到代码

建议模板不建议做分文件编写,如果要进行的话就要把声明和实现写到一个文件中

友元函数模板:

#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class person
{
    friend void func(person<T1, T2>&p)//全局函数做友元
    {
	cout << p.name << endl << p.ages << endl;
    }
public:
    person(T1 name, T2 ages)
    {
    	this->name = name;
    	this->ages = ages;
    }
private:
    T1 name;
    T2 ages;
};
void test()
{
    person<string, int>p("唐僧",88);
    func(p);//虽然没在全局声明但是默认func是全局函数做友元
}

int main()
{
    test();
    return 0;
}

普通函数,模板函数,模板函数就是函数前面紧跟着的有template<class T... >,普通函数没有,想强制调用模板函数就要使用空参数列表<>

类模板应用

#include<iostream>
using namespace std;
template<class T>
class array
{
public:
    array(int capacity)//有参构造函数    实现array<int>p(10);
    {
	this->capacity = capacity;
	this->size = 0;
	this->myarray = new T[this->capacity];
    }
    array(const array &p)   //拷贝构造函数
    {
	this->capacity = p.capacity;
	this->size = p.size;
	this->myarray = new T[p.capacity];
	for (int i = 0; i < this->size; ++i)
	{
	    this->myarray[i] = p[i];     //这里不必写p.myarray[i],因为我们写了[]运算符的重载,目的就是为了让代码更简明
	}
    }
    array& operator=(const array &p)    //=号运算符的重载
    {
        if (this->capacity != NULL)
        {
	    delete[] this->myarray;
	    this->myarray = NULL;
	    this->size = NULL;
	    this->capacity = NULL;
        }
	this->capacity = p.capacity;
	this->size = p.size;
	this->myarray = new T[p.capacity];
	for (int i = 0; i < this->size; ++i)
	{
            this->myarray[i] = p[i];     //这里不必写p.myarray[i],因为我们写了[]运算符的重载,目的就是为了让代码更简明
	}
    return *this
}
    T operator[](int num)
    {
    	return this->myarray[num];
    }

    void push(int val)    //尾插
     {
    	this->myarray[this->size] = val;
    	size++;
    }
    int getsize()          //获取有效长度
    {
    	return this->size;
    }
    int getcapacity()      //获取容量
    {
    	return this->capacity;
    }
    ~array()           //析构函数
    {
    	if (this->capacity != NULL)
    	{
    		delete[] this->myarray;
    		this->size = NULL;
    		this->myarray = NULL;
    		this->capacity = NULL;
	}
    }
private:
    T *myarray;
    int capacity;
    int size;
};


void printfs(array<int>& p)    //打印数组的函数
{
    for (int i = 0; i < p.getsize(); ++i)
    {
    	cout << p[i] << " ";
    }
    cout << endl;
}

void test()
{
    array<int>p1(10);
    int j = 10;
    for (int i = 0; i < p1.getcapacity(); ++i)     //进行插入数据
    {	
    	p1.push(j);
    }
    printfs(p1);
}
int main()
{
    test();
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值