C++泛型编程

server/2025/3/16 2:42:27/

感谢哔哩哔哩UP”开发者LaoJ“,以下是听课记录~

模板是C++实现泛型编程的手段,同一段代码逻辑可以接受多个类型的参数

无论是函数模板还是类模板,在编码后,需要分文件时,将其声明和定义放进.hpp文件中。不要将声明放.h,定义放.cpp,会报错

一、函数模板

对于函数模板,使用不同的类型对其进行实例化时,会生成多个不同的函数

当没有调用函数模板时,不会被实例化(延迟实例化)

1.1、接受类型参数

#include <iostream>
#include <string>
using namespace std;template <typename T>
void Swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}
/*允许为特定的数据类型提供定制的实现*当类型为int时,调用的是以下实现,而不是函数模板中的实现*/
void Swap(int& a, int& b)
{int tmp = a;a = 2 * b;b = 2 * tmp;
}int main(void)
{int val1 = 10, val2 = 20;cout << val1 << " " << val2 << endl;/*函数模板有自动推导*Swap<int>(val1, val2)与Swap(val1, val2)等价*/Swap<int>(val1, val2);cout << val1 << " " << val2 << endl;double d1 = 3.14, d2 = 6.78;cout << d1 << " " << d2 << endl;Swap(d1, d2);cout << d1 << " " << d2 << endl;return 0;
}

1.2、接受非类型参数作为常量 

#include <iostream>
#include <string>
using namespace std;template <int N>
void printNTimes(const string& str)
{for (int i = 0; i < N; ++i)cout << str << endl;
}int main(void)
{string str = "hello world!";printNTimes<5>(str);
}

二、类模板

2.1、类模板

类模板的类型参数可以有默认值(默认值从右到左,不能出现右边的没有默认值而左边的有默认值)

类模板没有自动推导的使用方式(在创建类对象时,必须显式说明类型)

/*没有自动推导方式*/
template<typename T1, typename T2>
clase myclass
{
public:myclass(T1 name, T2 age) : name(name), age(age) {}
private:T1 name;T2 age;
};myclass<string, int> obj("lisi", 20);       //正确
myclass obj("lisi", 20);                    //错误,要显示说明类型/*默认值*/
template<typename T1, typename T2 = int>    //正确,可以有默认值
template<typename T1 = string, typename T2> //错误,默认值应该从右到左

2.1.1、模板类在调用时,才会被实例化

#include<iostream>
using namespace std;class me
{
public:void showme() {cout << "This is me" << endl;}
};template <typename T>
class myclass
{
public:void test() {T obj;obj.showme();   //未定义}
};int main(void)
{myclass<me> obj;obj.test();return 0;
}

2.1.2、在模板类内声明函数,在类外定义函数

#include<iostream>
using namespace std;class me
{
public:void showme() {cout << "This is me" << endl;}
};template <typename T>
class myclass
{
public:void test();
};/*函数在类外进行定义*/
template <typename T>
void myclass<T>::test() {T obj;obj.showme();
}int main(void)
{myclass<me> obj;obj.test();return 0;
}

2.1.3、当模板类作为函数参数时

#include<iostream>
#include<string>
using namespace std;template <typename T1, typename T2>
class myclass
{
public:myclass(T1 name, T2 age) : name(name), age(age) {}void showme() {cout << "name:" << name << " " << "age:" << age << endl;}
private:T1 name;T2 age;
};/*方法一:确定具体的类型传入*/
void func1(myclass<string, int> obj) 
{obj.showme();
}/*方法二:参数模板化*/
template <typename T1, typename T2>
void func2(myclass<T1, T2> obj) 
{obj.showme();
}/*方法三:将类模板化*/
template <typename T>
void func3(T& obj) 
{obj.showme();
}int main(void) 
{myclass<string, int> obj("lisi", 20);func1(obj);func2(obj);func2(obj);return 0;
}

2.2、类模板与继承

#include <iostream>
using namespace std;/*基类是模板类*/
template <typename T>
class Base {
public:Base(T value) : data(value) {}void show() {cout << "Base data: " << data << endl;}
protected:T data;
};/*情况一:派生类不是模板类*/
//方法一:派生类继承模板基类的特化版本(例如 int)
class DerivedInt : public Base<int> {
public:DerivedInt(int value) : Base<int>(value) {}  //在此处,调用了Base<int>类的构造函数void display() {cout << "DerivedInt data: " << data << endl;}
};
//方法二:派生类继承模板基类(仍然是模板)
template <typename T>
class DerivedTemplate : public Base<T> {
public:DerivedTemplate(T value) : Base<T>(value) {}void display() {cout << "DerivedTemplate data: " << this->data << endl;}
};/*情况二:派生类是模板类*/
template <typename T, typename U>
class Derived : public Base<T> {
public:Derived(T baseValue, U derivedValue) : Base<T>(baseValue), extraData(derivedValue) {}void display() {cout << "Base data: " << this->data << ", Derived data: " << extraData << endl;}
private:U extraData;
};int main() {/*对于情况一*/DerivedInt obj1(10);obj1.show();obj1.display();DerivedTemplate<double> obj2(3.14);obj2.show();obj2.display();/*对于情况二*/Derived<int, double> obj3(10, 3.14);obj3.show();     // 调用基类方法obj3.display();  // 调用派生类方法return 0;
}

2.3、友元函数与模板类

#include <iostream>
#include <string>
using namespace std;// 前向声明模板类和函数print
template <typename T1, typename T2>
class Base;
template <typename T1, typename T2>
void print(Base<T1, T2>& obj);template <typename T1, typename T2>
class Base {
public:Base(T1 name, T2 age) : name(name), age(age) {}/*在类内定义友元函数*/friend void show(Base<T1, T2>& obj) {cout << "show:" << endl;cout << "name:" << obj.name << " " << "age:" << obj.age << endl;}friend void print<T1, T2>(Base<T1, T2>& obj);
private:T1 name;T2 age;
};/*在类外定义友元函数*一、需要向前声明模板类和友元函数*二、在类中声明友元函数*三、在类外定义友元函数*/
template <typename T1, typename T2>
void print(Base<T1, T2>& obj) {cout << "print: " << endl;cout << "name:" << obj.name << " " << "age:" << obj.age << endl;
}int main(void) {Base<string, int> obj("lisi", 20);show(obj);print(obj);return 0;
}

http://www.ppmy.cn/server/175305.html

相关文章

247g 的工业级电调,如何让无人机飞得更 “聪明“?——STONE 200A-M 深度测评

一、轻量化设计背后的技术取舍 当拿到 STONE 200A-M 时&#xff0c;247g 的重量让人意外 —— 这个接近传统 200A 电调 70% 的重量&#xff0c;源自 1205624.5mm 的紧凑结构&#xff08;0.1mm 公差控制&#xff09;。实测装机显示&#xff0c;相比同规格产品&#xff0c;其体积…

python基础内置变量

1. __name__: 作用&#xff1a;用于标识当前模块的名称。当一个 Python 文件被直接运行时&#xff0c;__name__ 的值为 "__main__"&#xff1b;当该文件作为模块被其他文件导入时&#xff0c;__name__ 的值为该文件的文件名&#xff08;不包含 .py 后缀&#xff09;…

AI数字人源码开发---SaaS化源码部署+PC+小程序一体化

#数字人#数字人分身#123数字人#数字人分身源码部署搭建 AI数字人源码开发步骤 确定功能需求&#xff1a;首先确定需要实现的功能和特性&#xff0c;包括语音识别、自然语言处理、人脸识别等功能。这些功能将构成AI数字人的核心功能。 开发AI数字人源码&#xff1a;使用合适的…

论文调研 | 一些开源的AI代码生成模型调研及总结【更新于250313】

本文主要介绍主流代码生成模型&#xff0c;总结了基于代码生成的大语言模型&#xff0c;按照时间顺序排列。 在了解代码大语言模型之前&#xff0c;需要了解代码相关子任务 代码生成 文本生成代码(Text to code):根据自然语言描述生成代码 重构代码&#xff08;Refactoring …

人工智能与人的智能,改变一生的思维模型分享【4】决策树

决策树&#xff08; DECISION TREE&#xff09; 一般由一个决策图和若干可能的结果组成。是一种通过罗列解题的关键步骤以及各步骤发生的条件和结果&#xff0c;由此来创建到达目标的规划。 我们很早就知道有一个方法&#xff0c;叫做当你苦闷、纠结的时候&#xff0c;把你的所…

PyQt基础——简单的图形化界面(窗口)

一、代码展示 import sysfrom PyQt6.QtGui import QPixmap from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QLineEdit, QPushButton from PyQt6 import uic from PyQt6.QtCore import Qt# 封装一个我的窗口类 class MyWidget(QWidget):def __init__(self):supe…

list常用接口及模拟实现

目录 基础构造 常用接口 1>常见构造 2>容量操作 3>遍历操作 4>修改操作 5>其它操作 模拟实现 a.节点 b.迭代器 c.链表 list与vector 基础构造 list是一种基于双向循环链表的容器&#xff0c;提供了灵活的元素插入、删除和遍历操作 &#xff08;如…

单机DeepSeek做PPT,YYDS!

今天同事问我 AI 能不能做 PPT&#xff0c;有个述职报告要做&#xff0c;问我能不能帮忙&#xff0c;这时我脑海中的第一画面就是 DeepSeek Kimi DeepSeek 擅长逻辑构建与内容生成&#xff0c;其深度思考能力当前测试下来&#xff0c;不愧为国内No.1&#xff0c;而且还会把中间…