C++之8|模板与特化

八、模板

1、类型模板1-模板函数

例36、template(1)

假如我现在想实现简单的加法运算,那么就要考虑数据的类型。先考虑只有两种情况:整数的和小数的。

于是就可以确定案例函数有add(1, 2)add(1.1, 2.3),如下

#include <stdio.h>
#include <iostream>

using namespace std;

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

double add(double a, double b)
{
    
    
	return a+b;
}

int main()
{
    
    
	cout<< add(1, 2) <<endl;
	cout<< add(1.1, 2.3) <<endl;
}

执行结果

@ubuntu:/mnt/hgfs/ub2$ g++ template1.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
3
3.4
@ubuntu:/mnt/hgfs/ub2$ 

然后就发现这个add()函数只是类型不同,实现方式都是一样。这时候模板的妙处就展现出来了。

如下

#include <stdio.h>
#include <iostream>

using namespace std;

template<typename XXX>
XXX add(XXX a, XXX b)
{
    
    
	return a+b;
}

int main()
{
    
    
	cout<< add(1, 2) <<endl;
	cout<< add(1.1, 2.3) <<endl;
}

执行结果一样

@ubuntu:/mnt/hgfs/ub2$ g++ template2.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
3
3.4
@ubuntu:/mnt/hgfs/ub2$ 

2、类型模板2-模板类

例37、template(2)

回顾之前的例11例23例25arr.h

#ifndef _ARR_
#define _ARR_

class ARR{
    
    
public:
	ARR():tail(0){
    
    
	}

	void addtail(int data);
	void show(void);
private:
	int data[100];
	int tail;
};

#endif

发现私有成员data[100] 的数据类型是固定死了的(int),后面凡是数据都得整型int处理,比如3.7就会当成3,使数据出错。为了变得通用,就可以使用模板来处理,从而灵活运用。案例如下

arr.h

#ifndef _ARR_
#define _ARR_

template <typename XXX>

class ARR{
    
    
public:
	ARR():tail(0){
    
    
	}

	void addtail(XXX data);
	void show(void);
private:
	XXX data[100];
	int tail;
};

#endif

arr.cpp

#include "arr.h"
#include <stdio.h>
#include <iostream>

using namespace std;

template <typename XXX>

void ARR<XXX>::addtail(XXX data)
{
    
    
    	this->data[tail++] = data;
}

template <typename XXX>
void ARR<XXX>::show(void)
{
    
    
    	int i = 0;
    	for(; i<tail; i++)
				cout<< data[i] << ',';
    	cout << endl;
}

main.cpp

#include "arr.h"

int main()
{
    
    
    ARR<int> arr;
    
    arr.addtail(1);
    arr.addtail(3);
    arr.addtail(6);
    arr.addtail(9);
    
    arr.show();
}

运行结果

@ubuntu:/mnt/hgfs/ub2/ARR1$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR1$ g++ *.cpp
/tmp/ccm4VpzB.o: In function `main':
main.cpp:(.text+0x39): undefined reference to `ARR<int>::addtail(int)'
main.cpp:(.text+0x4d): undefined reference to `ARR<int>::addtail(int)'
main.cpp:(.text+0x61): undefined reference to `ARR<int>::addtail(int)'
main.cpp:(.text+0x75): undefined reference to `ARR<int>::addtail(int)'
main.cpp:(.text+0x84): undefined reference to `ARR<int>::show()'
collect2: error: ld returned 1 exit status
@ubuntu:/mnt/hgfs/ub2/ARR1$ 

出现这个问题是因为在C++中不支持模板分两部分来写(arr.carr.h

所以需要把这两个整合到一块去(整合到arr.h 中),成如下的arr.h

#ifndef _ARR_
#define _ARR_
#include <iostream>

using namespace std;


template <typename XXX>
class ARR{
    
    
public:
	ARR():tail(0){
    
    
	}

	void addtail(XXX data);
	void show(void);
private:
	XXX data[100];
	int tail;
};


template <typename XXX>
void ARR<XXX>::addtail(XXX data)
{
    
    
    	this->data[tail++] = data;
}

template <typename XXX>
void ARR<XXX>::show(void)
{
    
    
    	int i = 0;
    	for(; i<tail; i++)
				cout<< data[i] << ',';
    	cout << endl;
}

#endif

main.cpp 保持之前那样

#include "arr.h"

int main()
{
    
    
    ARR<int> arr;
    
    arr.addtail(1);
    arr.addtail(3);
    arr.addtail(6);
    arr.addtail(9);
    
    arr.show();
}

运行结果

@ubuntu:/mnt/hgfs/ub2/ARR2$ ls
a.out  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR2$ g++ main.cpp 
@ubuntu:/mnt/hgfs/ub2/ARR2$ ./a.out
1,3,6,9,
@ubuntu:/mnt/hgfs/ub2/ARR2$ 

然后假设我添加的是浮点数,可以改写如下

#include "arr.h"

int main()
{
    
    
#if 0
    ARR<int> arr;
    arr.addtail(1);
    arr.addtail(3);
    arr.addtail(6);
    arr.addtail(9);
#endif
    ARR<double> arr;
    arr.addtail(1.7);
    arr.addtail(3.5);
    arr.addtail(6.8);
    arr.addtail(9.6);
    
    arr.show();
}

执行结果依然没问题

@ubuntu:/mnt/hgfs/ub2/ARR2$ ls
a.out  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR2$ g++ main.cpp 
@ubuntu:/mnt/hgfs/ub2/ARR2$ ./a.out
1.7,3.5,6.8,9.6,
@ubuntu:/mnt/hgfs/ub2/ARR2$ 

这就是模板的魅力!!!

3、非类型模板

template <class T, int SIZE>
class List{
    
    
public:
    	List();
    	~List();
private:
    	T arr[SIZE];
    	int num;
};

例38、template(3)

参照例37,把数组大小也变为模板方式

arr.h

#ifndef _ARR_
#define _ARR_

#include <iostream>

using namespace std;

template <typename XXX, int SIZE>
class ARR{
    
    
public:
	ARR():tail(0){
    
    
	}

	void addtail(XXX data);
	void show(void);
	
private:
	XXX data[SIZE];
	int tail;
};

template <typename XXX, int SIZE>
void ARR<XXX, SIZE>::addtail(XXX data)
{
    
    
	this->data[tail++] = data;
}

template <typename XXX, int SIZE>
void ARR<XXX, SIZE>::show(void)
{
    
    
	int i = 0;
	for(;i<tail; i++)
		cout<< data[i] <<',';
	cout<<endl;
}

#endif

main.cpp

#include "arr.h"

int main()
{
    
    
	ARR<int, 100> arr;//类型为int,size为100

	arr.addtail(1);
	arr.addtail(3);
	arr.addtail(6);
	arr.addtail(9);

	arr.show();

	ARR<double, 1000> arr1;//类型为double,size为1000

	arr1.addtail(1.7);
	arr1.addtail(3.5);
	arr1.addtail(6.8);
	arr1.addtail(9.6);

	arr1.show();
}

执行结果

@ubuntu:/mnt/hgfs/ub2/ARR3$ ls
a.out  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR3$ g++ main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR3$ ./a.out
1,3,6,9,
1.7,3.5,6.8,9.6,
@ubuntu:/mnt/hgfs/ub2/ARR3$ 

4、特化

特化

template <>
class List{
    
    
public:
    	List();
    	~List();
private:
    	int arr[100];
    	int num;
};

偏特化

template <class A, class B>
class C{
    
    
public:
    	A a;
    	B b;
};
/*********************************/
class C<int, B>{
    
    //特化B为int 类型,至于A什么类型并没有没有特化,这种有针对的特化就是偏特化
    
};

例39、template(4)

例36中我们已经实现int类型和double类型公用的模板,但现在遇到个判断真假的逻辑加法运算需求(全真才为真,否则为假)。

然后发现这个模板不管用了。

#include <stdio.h>
#include <iostream>

using namespace std;

template<typename XXX>
XXX add(XXX a, XXX b)
{
    
    
	return a+b;
}

int main()
{
    
    
#if 0
	cout<< add(1, 2) <<endl;
	cout<< add(1.1, 2.3) <<endl;
#endif
	cout<< add(true, false) <<endl;
	cout<< add(true, true) <<endl;
}

运行结果

@ubuntu:/mnt/hgfs/ub2$ g++ template3.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
1
@ubuntu:/mnt/hgfs/ub2$ 

根据需求,一真一假结果为假即为0,而这里是1,所以是错误的。于是我们可以使用特化来解决此问题。

#include <stdio.h>
#include <iostream>

using namespace std;

template<typename XXX>
XXX add(XXX a, XXX b)
{
    
    
	return a+b;
}

template <>
bool add(bool a, bool b)
{
    
    
	if(a == true && b == true)
		return true;
	return false;
}

int main()
{
    
    
#if 0
	cout<< add(1, 2) <<endl;
	cout<< add(1.1, 2.3) <<endl;
#endif
	cout<< add(true, false) <<endl;
	cout<< add(true, true) <<endl;
}

运行结果

@ubuntu:/mnt/hgfs/ub2$ g++ template3.cpp 
@ubuntu:/mnt/hgfs/ub2$ ./a.out
0
1
@ubuntu:/mnt/hgfs/ub2$ 

猜你喜欢

转载自blog.csdn.net/weixin_44035986/article/details/125704518