第十二站(20天):C++泛型编程

模板

C++提供了模板(template)编程的概念。所谓模板,实际上是建立一个通用函数或类,
类内部的类型和函数的形参类型不具体指定 ,用一个虚拟的类型来代表。这种通用的方式称
为模板。 模板是泛型编程的基础, 泛型编程即以一种独立于任何特定类型的方式编写代码
如: vector

函数模板(可以嵌套使用)

模板函数就是函数模板的自动实现

功能:
使用函数体相同的函数都可以用这个模板替代
实现多个函数用来返回两个数的最大值,要求能支持 char 类型、int 类型、double
template
如:
        template //这里的类属参数 T在下面函数体的 参数中必须出现一次
        T Max(T a, T b) {
            return a > b ? a : b;
        }
形式:
cout << Max(a, b) << endl;//编译器自动推导类型
cout << Max(a,b)<
第十二站(20天):C++泛型编程_第1张图片
#include 
using namespace std;

template 
T Max(T a, T b) {
	return a > b ? a : b;
}
int main(void) {
	int a = 4;
	int b = 5;
	float x = 1.2f;
	float y = 2.6f;
	cout << Max(a, b) << endl;//编译器自动推导类型
    cout << Max(a,b)<

函数模板和函数重载

//当函数模板和普通函数都符合调用时,优先选择普通函数
//Max(a,b);
//如果 显式指定类型 的使用函数模板,则使用<> 类型列表
//Max<>(a, b);
//如果函数模板会产生更好的匹配,使用函数模板

 函数模板的调用机制

函数模板在调用的时候,会根据调用者的数据类型,创建一个匹配的函数

类模板

类模板和函数模板一致

在类使用数据类型的地方都可以用模板的类属参数进行替换

(成员数据的数据类型,构造函数的参数类型,成员函数的返回值类型)

注:在模板类定义对象的时候必须指定为显示指定类型<>

当为单个参数时:

#include 
using namespace std;
template 
class A {
public:
	A(T a) {
		this->a = a;
	}
	T getA() {
		return a;
	}
private:
	T a;
};

int main(void) {
	A aa(666);
	cout << aa.getA() << endl;

	return 0;
}

当为多个参数时

第十二站(20天):C++泛型编程_第2张图片

#include 
using namespace std;
template 
class A {
private:
	T1 a;
	T2 b;
public:
	A(T1 a ,T2 b) {
		this->a = a;
		this->b = b;
	}
	T1 getA() {
		return a;
	}
	T2 getB() {
		return b;
	}
};

int main(void) {
	A aa(12,4.5);
	cout << aa.getA() << endl;
	cout << aa.getB() << endl;
	return 0;
}

当类作为函数参数的时候

 double add(A& a) {
    double sum = 0;
    sum = a.getA() + a.getB();
    return sum;
}

当子类继承父类(父类为模板类时)

 class B :public A {
    B(int a, double b):A(a,b) {}
};

当子类是模板类,父类是一般类时 

 和普通继承一样

#include 
using namespace std;

class B {
protected:
	int  a;
	double  b;
public:
	B(int a=1, double b=1.2) {
		this->a = a;
		this->b = b;
	}
};

template 
class A :public B{
public:
	A();
	A(T1 a, T2 b) :B(a, b) {}
	T1 getA() {
		return a;
	}
	T2 getB() {
		return b;
	}
};

double add(A& a) {
	double sum = 0;
	sum = a.getA() + a.getB();
	return sum;
}
int main(void) {
	A aa(12,12.2);
	cout << aa.getA() << endl;
	cout << aa.getB() << endl;
	return 0;
}

当子类和父类都是模板类

和普通继承一样

第十二站(20天):C++泛型编程_第3张图片

#include 
using namespace std;

template 
class B {
public:
	B(T1 a, T2 b){
		this->a = a;
		this->b = b;
	}
	T1 getA() {
		return a;
	}
	T2 getB() {
		return b;
	}
protected:
	T1 a;
	T2 b;
};

template 
class A :public B{
public:
	A();
	A(T1 a, T2 b) :B(a, b) {}
	T1 getA() {
		return a;
	}
	T2 getB() {
		return b;
	}
};

double add(A& a) {
	double sum = 0;
	sum = a.getA() + a.getB();
	return sum;
}
int main(void) {
	A aa1(10, 10.2);
	cout << aa1.getA() << endl;
	cout << aa1.getB() << endl;
	A aa(12,12.2);
	cout << aa.getA() << endl;
	cout << aa.getB() << endl;

	return 0;
}

类模板和友元函数 

 

(1) 类内部声明友元函数,必须写成一下形式
template < typename T>
friend A addA (A &a, A &b);
(2) 友元函数实现 必须写成
template < typename T>
A add(A &a, A &b) {
        //......
}
(3) 友元函数调用 必须写成
A< int > c4 = addA (c1, c2);

 类模板的封装

这里仅分为两个文件(.h和.cpp+main.cpp)

第十二站(20天):C++泛型编程_第4张图片

函数前声明 template
< 类型形式参数表 >
类的成员函数前的 类限定域说明必须要带上虚拟参数列表
template
A::A(T1 a)
{
    this->a = a;
}
返回的变量是模板类的对象时必须带上虚拟参数列表
T1 A::getA() {
    return a;
}
成员函数参数中出现模板类的对象时必须带上虚拟参数列表(也可以不带)
A A::operator+( const A & other)
{
    A tmp = this->a + other.a;
    return tmp.a;
}
成员函数内部没有限定( 可带可以不带 )
A A::operator+( const A & other)
{
  
 A tmp = this->a + other.a;
    return tmp.a;
}
.h
#include 
using namespace std;

template 
class A {
public:
	A(T1 a);
	T1 getA();
	A operator+(const A& other);
	void print();
private:
	T1 a;
};

.cpp
#include 
using namespace std;
#include "A.h"

template
A::A(T1 a)
{
	this->a = a;
}
template 
T1 A::getA() {
	return a;
}
template
A A::operator+(const A& other)
{
	A tmp = this->a + other.a;
	return tmp.a;
}

template
void A::print()
{
	cout << this->a << endl;
}
int main(void) {
	A a(12);
	A b(11);
	A c = a + b;
	c.print();
	return 0;
}

 这里仅分为三个文件(.h 和  .cpp  和  main.cpp)

如果分为这三个文件,那么只包含.h头文件就会报错C++ 类模板“无法解析的外部符号

在封装有三个文件的时候mian.cpp中就不用包含.h头文件了,仅包含.cpp文件即可

#include
using namespace std;

//#include "A.h"//同时包含两个或者仅包含.h都会报错
#include "A.cpp"

int main(void) {
    A a(12);
    A b(11);
    A c = a + b;
    c.print();
    return 0;
}

 类模板的静态成员数据

  从类模板实例化的每个模板类有自己的类模板数据成员,该 模板类的所有对象共享
一个 static 数据成员
和非模板类的 static 数据成员一样, 模板类的 static 数据成员也应该在文件范围定
义和初始化
  static 数据成员也可以使用虚拟类型参数 T

public:

        static T1 count;

//初始化静态成员数据
template
T1 A::count = 66;

//通过对象a对静态count赋值后
cout << a.count << endl;
a.count = 888;
cout << b.count << endl;
b.count = 1000;
cout << a.count << endl; 

第十二站(20天):C++泛型编程_第5张图片

 

你可能感兴趣的:(c++,开发语言,奇牛编程,visual,studio)