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

这篇具有很好参考价值的文章主要介绍了第十二站(20天):C++泛型编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

模板

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

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

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

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

template <typename T>
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<int>(a,b)<<endl;//显示类型调用
	cout << Max(x, y) << endl;
	return 0;
}

函数模板和函数重载

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

 函数模板的调用机制

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

类模板

类模板和函数模板一致

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

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

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

当为单个参数时:

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

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

	return 0;
}

当为多个参数时

第十二站(20天):C++泛型编程,c++,开发语言,奇牛编程,visual studio

#include <iostream>
using namespace std;
template <typename T1,typename T2>
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<int, double> aa(12,4.5);
	cout << aa.getA() << endl;
	cout << aa.getB() << endl;
	return 0;
}

当类作为函数参数的时候

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

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

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

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

 和普通继承一样

#include <iostream>
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 <typename T1, typename T2>
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<int, double>& a) {
	double sum = 0;
	sum = a.getA() + a.getB();
	return sum;
}
int main(void) {
	A<int ,double> aa(12,12.2);
	cout << aa.getA() << endl;
	cout << aa.getB() << endl;
	return 0;
}

当子类和父类都是模板类

和普通继承一样

第十二站(20天):C++泛型编程,c++,开发语言,奇牛编程,visual studio

#include <iostream>
using namespace std;

template <typename T1, typename T2>
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 <typename T1, typename T2>
class A :public B<int, double>{
public:
	A();
	A(T1 a, T2 b) :B(a, b) {}
	T1 getA() {
		return a;
	}
	T2 getB() {
		return b;
	}
};

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

	return 0;
}

类模板和友元函数 

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

 类模板的封装

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

第十二站(20天):C++泛型编程,c++,开发语言,奇牛编程,visual studio

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

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

.cpp
#include <iostream>
using namespace std;
#include "A.h"

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

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

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

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

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

#include <iostream>
using namespace std;

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

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

类模板封装多参

算术运算符重载多参

template<typename T1, typename T2>
A1<T1, T2> A1<T1, T2>::operator+(const A1<T1,T2>& other)
{
    A1<T1, T2> tmp{ this->a + other.a,this->b + other.b };
    return tmp;

输出运算符重载多参

template<typename T1, typename T2>
friend ostream& operator<<(ostream& os, const A1<T1, T2>& other);//设置为友元

template<typename T1, typename T2>
ostream& operator<<(ostream& os, const A1<T1, T2>& other)
{
    //“T1 A1<T1,double>::getA(void)”: 
    // 不能将“this”指针从“const A1<int,double>”转换为“A1<int,double> 
    //是因为传入的是const引用,但是调用了非const方法。
    os << other.getA() << " " << other.getB() << endl;
    //os << other.a <<" " << other.b << endl;
    return os;
}

 .h

#pragma once

#include <iostream>
using namespace std;

template <typename T1, typename T2>
class A1 {
public:
    A1(T1 a, T2 b);
    T1 getA()const;
    T2 getB()const;
    A1<T1, T2> operator+(const A1& other);
    template<typename T1, typename T2>
    friend ostream& operator<<(ostream& os, const A1<T1, T2>& other);
public:
    T1 a;
    T2 b;
};

template<typename T1, typename T2>
ostream& operator<<(ostream& os, const A1<T1, T2>& other)
{
    os << other.getA() << " " << other.getB() << endl;
    //os << other.a <<" " << other.b << endl;
    return os;
}

 .cpp

#include "A1.h"
#include <iostream>
using namespace std;
template<typename T1, typename T2>
A1<T1, T2>::A1(T1 a, T2 b):a(a),b(b)
{
}
template <typename T1, typename T2>
T1 A1<T1, T2>::getA() const{
    return a;
}
template<typename T1, typename T2>
T2 A1<T1, T2>::getB()const {
    return b;
}

template<typename T1, typename T2>
A1<T1, T2> A1<T1, T2>::operator+(const A1<T1,T2>& other)
{
    A1<T1, T2> tmp{ this->a + other.a,this->b + other.b };
    return tmp;
}

主函数

#include <iostream>
#include "A1.cpp" //这里不要包含错了
int main(void) {
    A1<int, double> a(12, 3.3), b(13, 32.9);
    A1<int, double> c = a + b;
    cout << c << endl;
    return 0;
}

 

 类模板的静态成员数据

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

public:

        static T1 count;

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

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

第十二站(20天):C++泛型编程,c++,开发语言,奇牛编程,visual studio文章来源地址https://www.toymoban.com/news/detail-814245.html

到了这里,关于第十二站(20天):C++泛型编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust程序语言设计 第十二章 一个 I/O 项目:构建一个命令行程序

    本章既是一个目前所学的很多技能的概括,也是一个更多标准库功能的探索。我们将构建一个与文件和命令行输入/输出交互的命令行工具来练习现在一些你已经掌握的 Rust 技能。 Rust 的运行速度、安全性、单二进制文件输出和跨平台支持使其成为创建命令行程序的绝佳选择,

    2024年02月13日
    浏览(29)
  • 第十二篇【传奇开心果系列】Ant Design Mobile of React开发移动应用:内置组件实现酷炫CSS 动画

    第一篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:从helloworld开始 第二篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:天气应用 第三篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:健身追踪 第四篇【传奇开心果系列】Ant Design Mobile of React 开发移

    2024年01月20日
    浏览(48)
  • 【正点原子STM32连载】 第十二章 SYSTEM文件夹介绍 摘自【正点原子】STM32F103 战舰开发指南V1.2

    1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html SYSTEM文件夹里面的代码由正点原子提供,是STM32F1xx系列的底层核心驱动函数,可以用在STM32F1xx系列的

    2024年02月05日
    浏览(47)
  • C#(六十二)之泛型的约束

    类型约束 基类约束有两个重要的目的。 1:它允许在泛型类中使用有约束指定的基类成员。 2:确保只能使用支持指定基类或派生类的类型实例。 约束是使用 where 上下文指定的。 下表列出了五种类型的约束: 约束 说明 T:struct 类型参数必须是值类型。可以指定除

    2024年02月17日
    浏览(31)
  • Go语言开发小技巧&易错点100例(十二)

    往期回顾: Go语言开发小技巧易错点100例(一) Go语言开发小技巧易错点100例(二) Go语言开发小技巧易错点100例(三) Go语言开发小技巧易错点100例(四) Go语言开发小技巧易错点100例(五) Go语言开发小技巧易错点100例(六) Go语言开发小技巧易错点100例(七) Go语言开

    2024年02月19日
    浏览(22)
  • 【小尘送书-第十一期】编程的基石,开发的核心:《算法秘籍》

    大家好,我是小尘,欢迎你的关注!大家可以一起交流学习!欢迎大家在CSDN后台私信我!一起讨论学习,讨论如何找到满意的工作! 👨‍💻博主主页:小尘要自信 👨‍💻推荐专栏: 👨‍💻《1》开发环境配置攻略 👨‍💻《2》Java程序员的成长 👨‍💻《3》2023Java面试实

    2024年02月04日
    浏览(35)
  • 第十三章,枚举与泛型例题

    例题1 结果   例题2 结果   例题3 结果     例题4 结果 例题5  结果 例题6  结果 例题7  结果 例题8  结果

    2024年02月06日
    浏览(41)
  • 掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)

    通道(Channel)是用来在 Go 程序中传递数据的一种数据结构。它是一种类型安全的、并发安全的、阻塞式的数据传输方式,用于在不同的 Go 协程之间传递消息。 基本概念 创建通道 :使用 make() 函数创建一个通道。 发送数据 :使用 - 操作符向通道发送数据。 接收数据 :使用

    2024年03月21日
    浏览(49)
  • C语言编程经典100例——11至20例

    目录 第 11 例 第 12 例 第 13 例 第 14 例 第 15 例 第 16 例 第 17 例 第 18 例 第 19 例 第 20 例 程序源码: 程序运行结果: 程序源码: 程序运行结果: 程序源码: 程序运行结果: 程序源码: 程序运行结果: 程序源码: 程序运行结果: 程序源码: 程序运行结果: 程序源码:

    2024年02月07日
    浏览(31)
  • 学习笔记|计数器|Keil软件中 0xFD问题|I/O口配置|STC32G单片机视频开发教程(冲哥)|第十二集:计数器的作用和意义

    直流有刷的电机,后面两个一正一负的电接上,电机就可以转 到底是转子个几个圈呢? 我们就可以在背后加装这么一个码盘,我们假设这里是有60个这个光电的一个孔对吧 那我们转一圈是不是就可以一个轴上输出60个这样的脉冲,有遮挡就输出1,无遮挡输出0, 两路交替,如果说

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包