上篇C++57个入门知识点_55 函数模板(template<typename T>;T GetMin(T a, T b){};函数模板定义;隐式实例化;显式实例化;函数模板特例;实例化后模板才有效)介绍了函数模板的相关概念,本篇将介绍C++中长用到另一种模板-类模板。
总结:
1.类模板的定义:
- 对某一个类型进行变量的替换
- 类模板放在
.h
文件中
2.类模板的显式实例化: 类模板中是无法使用隐式实例化,只能使用显示实例化
3.类模板的写法:
- 类模板写在类内
- 类模板写在类外
4.类模板的函数特例
1. 类模板的定义
类模板:
顾名思义即把类作为一个模板
类模板:
- 对某一个类型进行变量的替换
- 类模板放在
.h
文件中
以下CTest
类中定义返回为对象的函数
#include <iostream>
class CTest {
public:
CTest& foo(CTest& obj) {
return *this;
}
private:
int m_nInt;
};
int main(int argc, char* argv[])
{
CTest t;
return 0;
}
在类模板中,将上面成员变量int m_nInt;
的int
看做一个变量,假设用T
来表示,则对应类模板的定义方法有如下两种:
(1)使用class关键字
#include <iostream>
template <class T>
class CTest {
public:
CTest& foo(CTest& obj) {
return *this;
}
private:
T m_nInt;
};
int main(int argc, char* argv[])
{
CTest <int> t;
return 0;
}
(2)使用typename
关键字
一般而言不建议使用上述class
关键字的方式,其可能有类的关键字class
冲突,而使用函数模板中使用的typename
关键字。
#include <iostream>
template <typename T>
class CTest {
public:
CTest& foo(CTest& obj) {
return *this;
}
private:
T m_nInt;
};
int main(int argc, char* argv[])
{
CTest <int> t;
return 0;
}
2. 类模板的显式实例化
在
类模板中是无法使用隐式实例化,只能使用显示实例化
,因为使用隐式实例化是无法找到对应的数据类型的。除了上述的写法,还可以使用以
下多个参数和常量赋值
的形式。
书写方法:显式实例化CTest<int, double, 7> t
中template关键字被对应的类CTest替换,<int, double, 7> 为对应的数据类型
#include <iostream>
template<typename T, typename K = double, int n = 5>
class CTest {
public:
//写于类域内部
CTest& foo(CTest& obj) {
return *this;
}
private:
T m_nInt;
K m_nDouble;
int m = n;
};
int main(int argc, char* argv[])
{
//只能通过显式实例化使编译器猜对使用的类型
CTest<int, double, 7> t;
return 0;
}
运行结果:多个数据类型,对常量进行初始化
3. 类模板的写法
3.1 类模板写在类内
一般而言
,类模板是放在.h文件中
,类模板别人再用的时候是不希望编译的,放在
.cpp
中是不太好,它不能对
.cpp
产生对应的
obj
文件,不能编译。
具体写法如下:
- .h
#pragma once
//类模板
//对某一个类型进行变量的替换
//类模板放在.h文件中
//类模板的定义格式如下:
//支持多个及默认参操作
//template模板关键字、<typename T, typename K = double, int n = 5>类中包含的数据类型
//class CTest {}为类定义,其中T,K作为数据类型使用,类似于Int,double等,不好懂时用Int等代替理解
template<typename T, typename K = double, int n = 5>
class CTest {
public:
//写于类域内部
CTest& foo(CTest& obj) {
return *this;
}
private:
T m_nInt;
K m_nDouble;
int m = n;
};
- .cpp
#include <iostream>
#include"testCPP.h"
int main(int argc,char* argv[])
{
//只能通过显式实例化使编译器猜对使用的类型
CTest<int,double,7> t;
return 0;
}
3.2 类模板写在类外
类模板的函数体可以写在类内,也可以利用四饼连接符写在类外,上为写在类内,下为写在类外的形式。
我们知道,把函数写在类里面是函数内联,但有时候我们需要将函数声明和实现分开。可以通过以下的写法实现。
- .h
#pragma once
template<typename T>
class CTest {
public:
//写于类域内部
CTest& foo(CTest& obj);
private:
T m_nInt;
};
//写于类域外部的标准写法
template<typename T>
CTest<T>& CTest<T>::foo(CTest<T>& obj) {
T obj2;
return *this;
}
- .cpp
#include <iostream>
#include "testCPP.h"
int main(int argc, char* argv[])
{
//只能通过显式实例化使编译器猜对使用的类型
CTest<int> t;
return 0;
}
4. 类模板的函数特例
有时候,类模板内的函数也需要特例时可以如下去写:
- .h
#pragma once
template<typename T>
class CTest {
public:
//写于类域内部
CTest& foo(CTest& obj);
T get();
private:
T m_nInt;
};
//写于类域外部的标准写法
template<typename T>
CTest<T>& CTest<T>::foo(CTest<T>& obj) {
T obj2;
return *this;
}
//普通类模板成员函数
template<typename T>
T CTest<T>::get() {
return m_nInt;
}
//类模板成员函数特例
template<>
const char* CTest<const char*>::get() {
return "Hello";
}
- .cpp
#include <iostream>
#include "testCPP.h"
int main(int argc, char* argv[])
{
//类模板成员函数特例
CTest<char*> t;
char* p = t.get();
//非特例
CTest<int> t2;
int n = t2.get();
return 0;
}
5.学习视频地址:C++57个入门知识点_56 类模板