第一百一十三天学习记录:C++提高:类模板(黑马教学视频)

这篇具有很好参考价值的文章主要介绍了第一百一十三天学习记录:C++提高:类模板(黑马教学视频)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

类模板

类模板语法

类模板作用:
建立一个通用类,类中的成员 数据类型可以不具体定制,用一个虚拟的类型来代表。
语法:

template<typename T>
类

解释:
template … 声明创建模板
typename … 表面其后面的符号是一种数据类型,可以用class代替
T … 通用的数据类型,名称可以替换,通常为大写字母

#include <iostream>
using namespace std;
#include <string>

template<class NameType,class AgeType>
struct Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson()
	{
		cout << "name:" << this->m_Name << "age:" << this->m_Age << endl;
	}
	NameType m_Name;
	AgeType m_Age;
};

void test01()
{
	Person<string, int>p1("孙悟空", 999);
	p1.showPerson();
}

int main()
{
	test01();
	return 0;
}

总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为模板

类模板与函数模板区别

类模板与函数模板区别主要有两点:
1、类模板没有自动类型推导的使用方式
2、类模板在模板参数列表中可以有默认参数

#include <iostream>
using namespace std;
#include <string>

template<class NameType, class AgeType = int>
struct Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson()
	{
		cout << "name:" << this->m_Name << "age:" << this->m_Age << endl;
	}
	NameType m_Name;
	AgeType m_Age;
};

//1、类模板没有自动类型推导的使用方式
void test01()
{
	//Person p1("孙悟空", 999);//报错,无法用自动类型推导
	Person<string, int>p1("孙悟空", 999);
	p1.showPerson();
}
//2、类模板在模板参数列表中可以有默认参数
void test02()
{
	Person<string>p2("猪八戒",999);
	p2.showPerson();
}

int main()
{
	test01();
	test02();
	return 0;
}

总结:
1、类模板使用只能用显示指定类型方式
2、类模板中的模板参数列表可以有默认参数

类模板中成员函数的创建时机

类模板中成员函数和普通类中成员函数创建时机是有区别的:
1、普通类中的成员函数一开始就可以创建
2、类模板中的成员函数在调用时才创建

#include <iostream>
using namespace std;

class Person1
{
public:
	void showPersong1()
	{
		cout << "Person1 show" << endl;
	}
};

class Person2
{
public:
	void showPersong2()
	{
		cout << "Person2 show" << endl;
	}
};

template<class T>
class Myclass
{
public:
	T obj;
	//类模板中的成员函数
	void func1()
	{
		obj.showPerson1();
	}

	void func2()
	{
		obj.showPerson2();
	}
};

int main()
{

	return 0;
}

上述代码可以运行,因为没有调用成员函数。

#include <iostream>
using namespace std;

class Person1
{
public:
	void showPerson1()
	{
		cout << "Person1 show" << endl;
	}
};

class Person2
{
public:
	void showPerson2()
	{
		cout << "Person2 show" << endl;
	}
};

template<class T>
class Myclass
{
public:
	T obj;
	//类模板中的成员函数
	void func1()
	{
 		obj.showPerson1();
	}

	void func2()
	{
		obj.showPerson2();
	}
};

void test01()
{
	Myclass<Person1>m;
	m.func1();
	//m.func2();//报错
}

int main()
{
	test01();
	return 0;
}

总结:
类模板中的成员函数并不是一开始就创建的,在调用时才去创建

类模板对象做函数参数

学习目的:
类模板实例化出的对象,向函数传参的方式
一共有三种传入方式:
1、指定传入的类型 —— 直接显示对象的数据类型
2、参数模板化 —— 将对象中的参数变为模板进行传递
3、整个类模板化 —— 将这个对象类型模板化进行传递

#include <iostream>
using namespace std;
#include <string>

//类模板对象做函数参数
template<class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	void showPerson()
	{
		cout << "姓名:" << this->m_Name << " 年龄:" << this->m_Age << endl;
	}

	T1 m_Name;
	T2 m_Age;
};
//1、指定传入的类型 —— 直接显示对象的数据类型(最常用)
void printPerson1(Person<string, int>&p)
{
	p.showPerson();
}

void test01()
{
	Person<string, int>p("张三", 33);
	printPerson1(p);
}

//2、参数模板化 —— 将对象中的参数变为模板进行传递
template<class T1, class T2>
void printPerson2(Person<T1, T2>&p)
{
	p.showPerson();
	cout << "T1的类型为:" << typeid(T1).name() << endl;
	cout << "T2的类型为:" << typeid(T2).name() << endl;
}

void test02()
{
	Person<string, int>p("李四", 32);
	printPerson2(p);
}

//3、整个类模板化 —— 将这个对象类型模板化进行传递
template<class T>
void printPerson3(T &p)
{
	p.showPerson();
	cout << "T的数据类型为:" << typeid(T).name() << endl;
}

void test03()
{
	Person<string, int>p("王五", 35);
	printPerson3(p);
}

int main()
{
	test01();
	test02();
	test03();
	return 0;
}

第一百一十三天学习记录:C++提高:类模板(黑马教学视频),编程语言学习,c++,学习
总结:
1、通过类模板创建的对象,可以有三种方式向函数中进行传参
2、使用比较广泛的是第一种:指定传入的类型

类模板与继承

当类模板碰到继承时,需要注意以下几点:
1、当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
2、如果不指定,编译器无法给子类分配内存
3、如果想灵活指定出父类中T的类型,子类也需变为类模板

#include <iostream>
using namespace std;

template<class T>
class Base
{
	T m;
};

//class Son :public Base//错误,必须要知道父类中T的类型,才能继承给子类
class Son :public Base<int>
{

};

template<class T1,class T2>
class Son2 :public Base<T2>
{
public:
	Son2()
	{
		cout << "T1的类型为:" << typeid(T1).name() << endl;
		cout << "T2的类型为:" << typeid(T2).name() << endl;
	}
	T1 obj;
};

void test01()
{
	Son s1;
}

void test02()
{
	Son2<int, char>S2;
}

int main()
{
	//test01();
	test02();
	return 0;
}

第一百一十三天学习记录:C++提高:类模板(黑马教学视频),编程语言学习,c++,学习
总结:如果父类是类模板,子类需要指出父类父类中T的数据类型

类模板成员函数类外实现

学习目标:能够掌握类模板中的成员函数类外实现

#include <iostream>
using namespace std;
#include <string>

template<class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age);

	void showPerson();

	T1 m_Name;
	T2 m_Age;
};

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
}

void test01()
{
	Person<string, int>P("Tom", 20);
	P.showPerson();
}

int main()
{
	test01();
	return 0;
}

总结:类模板中成员函数类外实现时,需要加上模板参数列表

类模板分文件编写

学习目标:
掌握类模板成员函数分文件编写产生的问题以及解决方式

问题:
类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到

解决:
1、解决方式1:直接包含.cpp源文件
2、解决方式2:将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制
hpp

#pragma once
#include <iostream>
using namespace std;
#include <string>

//类模板分文件编写问题以及解决

template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);

	void showPerson();

	T1 m_Name;
	T2 m_Age;
};


template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
}

main

//第一种解决方式,直接包含源文件
//#include "person.cpp"//少用
//第二种解决方式,将h和cpp中的内容写到仪器,将后缀改为.hpp文件
#include "person.hpp"


void test01()
{
	Person <string, int>p("Jerry", 18);
	p.showPerson();
}

int main()
{
	test01();
	return 0;
}

总结:主流的解决方式是第二种,将类模板成员函数写到一起,并将后缀名改为.hpp

类模板与友元

学习目标:掌握类模板配合友元函数的类内和类外实现

全局函数类内实现-直接在类内声明友元即可
全局函数类外实现-需要提前让编译器知道全局函数的存在

#include <iostream>
using namespace std;
#include <string>

//通过全局函数 打印Person信息
//提前让编译器知道Person类存在
template<class T1, class T2>
class Person;

//类外实现
template<class T1, class T2>
void printPerson2(Person<T1, T2> p)
{
	cout << "类外实现--姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;
}

template<class T1, class T2>
class Person
{
	//全局函数 类内实现
	friend void printPerson(Person<T1, T2> p)
	{
		cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;
	}

	//全局函数 类外实现
	//加空模板参数列表
	//如果全局函数 是类外实现,需要让编译器提前知道这个函数的存在
	friend void printPerson2<>(Person<T1, T2> p);

public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
private:

	T1 m_Name;
	T2 m_Age;
};

//1、全局函数在类内实现

void test01()
{
	Person<string, int>p("Tom", 20);
	printPerson(p);
}

//2、全局函数在类外实现
void test02()
{
	Person<string, int>p("Jerry", 20);
	printPerson2(p);
}

int main()
{
	test01();
	return 0;
}

总结:建议全局函数做类内实现,用法简单,而且编译器可以直接识别。文章来源地址https://www.toymoban.com/news/detail-603820.html

到了这里,关于第一百一十三天学习记录:C++提高:类模板(黑马教学视频)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 第一百一十八回 如何获取蓝牙连接状态

    我们在上一章回中介绍了如何连接蓝牙设备相关的内容,本章回中将介绍如何获取蓝牙连接状态.闲话休提,让我们一起Talk Flutter吧。 我们在上一章回中介绍如何连接蓝牙设备,但是如何知道蓝牙设备是否连接成功呢?这就需要我们去获取蓝牙设备的连接状态,通过蓝牙设备

    2024年02月12日
    浏览(42)
  • 第一百一十九回 如何通过蓝牙设备读写数据

    我们在上一章回中介绍了如何获取蓝牙状态相关的内容,本章回中将介绍 如何通过蓝牙设备读写数据 。闲话休提,让我们一起Talk Flutter吧。 通过蓝牙设备读写数据有两种方法: 一种是读写Characteristics; 一种是读写Descriptor. 我们在本章回中介绍的读写数据本质上是读写 Cha

    2024年02月12日
    浏览(37)
  • 第一百一十二回 flutter_screenutil包

    我们在上一章回中介绍了屏幕适配相关的内容,本章回中将介绍 flutter_screenutil 包,该包主要用来实现屏幕适配.闲话休提,让我们一起Talk Flutter吧。 我们在本章回中介绍的包是 flutter_screenutil ,它主要用来做屏幕和字体大小的适配,它的实现原理和我们在上一章回中介绍的屏幕

    2024年02月13日
    浏览(41)
  • 客快物流大数据项目(一百一十三):注册中心 Spring Cloud Eureka

    文章目录 注册中心 Spring Cloud Eureka 一、Eureka 简介 二、架构图

    2023年04月25日
    浏览(42)
  • Android之关机/重启/recovery模式(一百一十五)

    1.方式一:App调用系统api 2.方式二:setprop 注意:在init的reboot.c中,           adb reboot -p命令其实就是调用的setprop命令开关机的。  3.方式三:

    2024年02月14日
    浏览(31)
  • Emacs之改造最快文本搜索工具ripgrep(一百一十九)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2024年02月15日
    浏览(32)
  • Emacs之实现跨程序选中自动复制功能(一百一十八)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2024年02月15日
    浏览(44)
  • 客快物流大数据项目(一百一十七):网关 Spring Cloud Gateway

    文章目录 网关 Spring Cloud Gateway 一、简介 1、功能特性

    2024年02月04日
    浏览(65)
  • C/C++基础讲解(一百一十九)之经典篇(最优美的图案)

    很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一样都是这么啃过来的,从不知到知知,懵懂到入门,每一步都走的很艰辛,课程上,大学老师基本上讲解上机实操得时间特别有

    2024年02月09日
    浏览(38)
  • 第一百二十三天学习记录:C++提高:STL-vector容器(下)(黑马教学视频)

    功能描述: 对vector容器进行插入、删除操作 函数原型: 总结: 尾插 push_back 尾删 pop_back 插入 insert(位置迭代器) 删除 erase(位置迭代器) 清空 clear 功能描述: 对vector中的数据的存取操作 函数原型: 总结: 除了用迭代器获取vector容器中元素,[]和at也可以 front返回容器第一个

    2024年02月13日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包