C++模板编程入门(2)

一、模板类的继承

1、模板类继承的多种情况(常见的)

类模板:不确定的类,类中用到了模板
模板类:确定的类,类中用到了模板

(1)类模板 继承 类模板

(2)类模板 继承 模板类

(3)类模板 继承 普通类

(4)普通类 继承 模板类

2、类模板继承类模板

(1)单模板参数,类模板继承类模板

(2)代码实战中学习

#include <iostream>
using namespace std;

template <typename T> class People
{
private:
    T attribute;
public:
    People(){};
    People(T my_attitude):attribute(my_attitude){};

    void print(void);
};

template <typename T> void People<T>::print(void)
{
    cout << "attribute = " << this->attribute << endl;
}

template <typename U> class Man: public People<U>
{
private:
    U P_attribute;
public:
    Man(){};
    Man(U a, U b):People<U>(a),P_attribute(b){};
    void Man_print(void);
};

template <typename U> void Man<U>::Man_print(void)
{
    cout << "P_attribute = " << this->P_attribute << endl;
}

int main(int argc, char *argv[])
{
    Man<string> s("sdsd", "dsds");

    s.print();
    s.Man_print();

    return 0;
}

(3)总结:在继承时,相当于用子类的模板参数U去实例填充了父类的模板参数T

(4)作用:用于构建模板化的类体系,写模板化的大框架

3、多模板参数

(1)2个或2个以上模板参数的情况
在这里插入图片描述
(2)代码实战中学习

#include <iostream>
using namespace std;

template <typename T1, typename T2> class People
{
private:
    T1 attribute1;
    T2 attribute2;
public:
    People(){};
    People(T1 my_attitude1, T2 my_attitude2):attribute1(my_attitude1),attribute2(my_attitude2){};

    void print(void);
};

template <typename T1, typename T2> void People<T1, T2>::print(void)
{
    cout << "attribute1 = " << this->attribute1 << endl;
    cout << "attribute2 = " << this->attribute2 << endl;
}


template <typename U1, typename U2> class Man: public People<U1, U2>
{
private:
    U1 P_attribute1;
    U2 P_attribute2;
public:
    Man(){};
    Man(U1 a, U2 b, U1 a1, U2 a2):People<U1, U2>(a, b),P_attribute1(a1),P_attribute2(a2){};
    void Man_print(void);
};

template <typename U1, typename U2> void Man<U1, U2>::Man_print(void)
{
    cout << "P_attribute1 = " << this->P_attribute1 << endl;
    cout << "P_attribute2 = " << this->P_attribute2 << endl;
}

int main(int argc, char *argv[])
{
    Man<string, int> s("sdsd", 18, "dsds", 20);

    s.print();
    s.Man_print();

    return 0;
}

(3)注意:多个模板参数是按照顺序对应的

4、类模板 继承 模板类

#include <iostream>
using namespace std;

template <typename T> class People
{
private:
    T attribute;
public:
    People(){};
    People(T my_attitude):attribute(my_attitude){};

    void print(void);
};

template <typename T> void People<T>::print(void)
{
    cout << "attribute = " << this->attribute << endl;
}

template <typename U> class Man: public People<double>//在这里将People类确定为double
{
private:
    U P_attribute;
public:
    Man(){};
    Man(double a, U b):People<double>(a),P_attribute(b){};//这里的a的类型也由此确定了
    void Man_print(void);
};

template <typename U> void Man<U>::Man_print(void)
{
    cout << "P_attribute = " << this->P_attribute << endl;
}

int main(int argc, char *argv[])
{
    Man<string> s(6.666,"asdasd");

    s.print();
    s.Man_print();

    return 0;
}

5、类模板 继承 普通类

#include <iostream>
using namespace std;

class People
{
private:
    double attribute;
public:
    People(){};
    People(double my_attitude):attribute(my_attitude){};

    void print(void);
};

void People::print(void)
{
    cout << "attribute = " << this->attribute << endl;
}

template <typename U> class Man: public People//
{
private:
    U P_attribute;
public:
    Man(){};
    Man(double a, U b):People(a),P_attribute(b){};//
    void Man_print(void);
};

template <typename U> void Man<U>::Man_print(void)
{
    cout << "P_attribute = " << this->P_attribute << endl;
}

int main(int argc, char *argv[])
{
    Man<string> s(6.666,"asdasd");

    s.print();
    s.Man_print();

    return 0;
}

6、普通类 继承 模板类

#include <iostream>
using namespace std;

template <typename T> class People
{
private:
    T attribute;
public:
    People(){};
    People(T my_attitude):attribute(my_attitude){};

    void print(void);
};

template <typename T> void People<T>::print(void)
{
    cout << "attribute = " << this->attribute << endl;
}

class Man: public People<double>//在这里将People类确定为double
{
private:
    string P_attribute;
public:
    Man(){};
    Man(double a, string b):People<double>(a),P_attribute(b){};//这里的a的类型也由此确定了
    void Man_print(void);
};

void Man::Man_print(void)
{
    cout << "P_attribute = " << this->P_attribute << endl;
}

int main(int argc, char *argv[])
{
    Man s(6.666,"asdasdsdfsdfoo");

    s.print();
    s.Man_print();

    return 0;
}

二、非类型模板参数和模板类型推导

1、非类型模版参数

详解阅读:参考 https://blog.csdn.net/lanchunhui/article/details/49634077
template<typename T, int MAXSIZE>
{
    T elems[MAXSIZE];
}

int  main(void)
{
	 Stack<int, 10> int10Stack;
	return 0;
}

	非类型模板参数是有类型限制的。一般而言,它可以是常整数(包括enum枚举类型)或者指向外部链接对象的指针。

2、模板的本质

参数化:将其作为参数一样,通过传参确定

(1)类型参数化
(2)值参数化
(3)类型和值都参数化
(4)本质:延迟绑定

3、类型推导的隐式类型转换

(1)在决定模板参数类型前,编译器执行隐式类型转换,有时候实际类型和看起来会不同

(2)编译器用值类型实例化函数模板,而不是用相应的引用类型

(3)编译器用指针类型实例化函数模板,而不是相应的数组类型

(4)去除const修饰,绝不会用const类型实例化函数模板,总是用相应的非const类型

(5)对于指针来说,指针和 const 指针是不同的类型。

2int a = 5;
int &b = a;
People<b>//实例化时会将int& 转换为 int3int a[5];
void func(a);		// 数组做实参,实际实参不是数组而是指针
People<a>4const int a = 5;
People<a>//实例化时会去除const5const int *p1;
int *p2;

4、模板和库

(1)模板无法单独编译,也就不能通过lib连接静态库的形式隐藏实现

(2)模板通常会把声明和定义写在头文件里,所以c++的模板总是开源的

(3)说明typename的一种用法,这种用法里typename不等同于class

详解阅读:https://www.cnblogs.com/cthon/p/9201649.html

注:本文章参考了《朱老师物联网大讲堂》课程笔记,并结合了自己的实际开发经历以及网上他人的技术文章,综合整理得到。如有侵权,联系删除!水平有限,欢迎各位在评论区交流。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嵌同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值