黑马程序员C++视频笔记(第三部分p167-p263)

黑马程序员C++视频笔记(第三部分p167-p263)_第1张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第2张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第3张图片

P170 模板-函数模板案例-数组排序
黑马程序员C++视频笔记(第三部分p167-p263)_第4张图片

#include 
using namespace std;
#include //(1)只要涉及string打印输出要加此文件!!!

//定义函数模板
template<class T>//(2)注意这后面不加分号,它和下边函数实一个整体!!!
void mysort(T arr[], int len) //(5)数组做参数且值引用传递形式
{
	//(3)选择排序法
	for (int i = 0; i < len; i++)
	{
		int max = i;
		for (int j = i + 1; j < len; j++) //选择法排序:每一次内循环都找到前j个数最大值下标
		{
			if (arr[max] < arr[j])
			{max = j;}
		}
		//交换最大值使其往前排
		if(max!=i)
		{
			T temp = arr[i];
			arr[i] = arr[max];
			arr[max] = temp;
		}
	}
}

template<typename T>
void myprint(T arr[],int len)//(5)数组做参数且值引用传递形式
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << endl;
	}
}
int main()
{
	int arr[3] = { 1,9,6 };
	char arr1[] = "defabc";
	int len = sizeof(arr1) / sizeof(arr1[0]);
	//mysort(arr[3], 3);//(4)错误!数组作为函数参数时,就直接单单写一个数组名!!!!!!!!!!!!!
	mysort(arr, 3);
	myprint(arr, 3);
	mysort(arr1, len);
	myprint(arr1, len);
		
	system("pause");
	return 0;
}

使用模板增加代码复用性!—模板就是把函数参数类型和返回值类型做为参数,根据情况选择函数参数和返回值类型!
注意:
(3)选择排序法!
(4)数组作为函数参数时,函数调用时无论是值引用还是引用传递都是直接单单写一个数组名!!!!!!
(5)数组做参数且值引用传递形式
.
问题:对数组那一块还是迷糊,对参数值传递和引用传递也迷糊,数组做参数涉及值和引用传递更迷!!!总结学习一下!
参考链接:https://blog.csdn.net/weixin_44997676/article/details/106636853

P17105 模板-普通函数与函数模板区别
黑马程序员C++视频笔记(第三部分p167-p263)_第5张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第6张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第7张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第8张图片
P17206 模板-普通函数与函数模板调用规则
黑马程序员C++视频笔记(第三部分p167-p263)_第9张图片

注意:规则1—如果只有普通函数的声明没有定义,就会报错,因为它还是去优先调用的普通函数。
规则2----空模板参数列表: 函数名< > (参数1,参数2…) 即加上尖括号且什么类型都不写!

P173 模板-模板的局限性
黑马程序员C++视频笔记(第三部分p167-p263)_第10张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第11张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第12张图片

#include 
using namespace std;
#include //(7)只要涉及string打印输出要加此文件!!!

//注意(1)模板不是万能的,对于有些特定的数据类型,需要用具体化方式做特殊实现!
//如:比较两个person类型数据是否相等。

class person//定义一个类//(5)注意一个类最基本的结构组成!
{
public: //(9)别忘了写访问权限啊!!!private,public,protect
//类成员
  //类属性
	string p_name;
	int p_age;
  //类成员函数(包括类构造和析构以及其他成员函数)
	//类构造函数
	person(string name,int age) 
	{   //此构造函数只是进行赋初值操作
		this->p_name = name;//(8)this???
		this->p_age = age;
	}
	//类其他成员函数

	//类析构函数

};

//定义一个比较两个自定义类型数据(person)是否相等的模板函数
template <class T>
bool MyCompare(T a, T b)
{
	if (a.p_name == b.p_name && a.p_age == b.p_age)
	{
		return true;
	}
	return false;
}

void test01()//(4)这样写在主函数调用的好处
{
 //实例化类对象(3)注意写法!
	//person a = { tom;12 };   //啥也不是!结构体跟类搞混了!这里person是一个类而不是结构体!而且即使是结构体赋值也不是这样!struct student s2 = {"li",13,80};
	//person p1(Tom, 13);//错误:“Tom”
	person p1("Tom", 13); //(6)注意:你看看上边定义了个类却没有写任何访问权限(private,public,protect),这里就无权访问,肯定报错啊!!!
	person p2("Tom", 13);//(2)注意:类的构造函数是在类实例化对象时自动调用! 注意实例化类对象写法!
	person p3 = person("mike", 15);//(2)实例化类对象也可以这样写!
	
	if (MyCompare<person>(p1,p2))
	{
		cout << "一样" << endl;
	}
	else
	{
		cout << "不一样" << endl;
	}
}

int main()
{
	test01();//(4)
	system("pause");
	return 0;
}

注意:
(2)注意:类的构造函数是在类实例化对象时自动调用! 注意实例化类对象写法!person p1(“Tom”, 13); 这一句就直接自动调用了类构造函数! //(2)实例化类对象也可以这样写:person p3 = person(“mike”, 15);
(4)这样写的好处,这样每一个测试我都写成一个函数放在main外边,这样main函数就很整洁,main中只去调用test01,test02…即可!
(5)注意一个类最基本的结构组成!
(9)别忘了写访问权限啊!!!private,public,protect啥也不写默认类成员私有,后面就无法使用!
.
.
拓展:本案例也可以使用运算符重载来解决!
本文链接:https://blog.csdn.net/weixin_42837024/article/details/82496017
本文链接:https://blog.csdn.net/jacket_/article/details/89714947

P174 模板-类模板基本语法(实质就是把类内部成员数据类型参数化!)
黑马程序员C++视频笔记(第三部分p167-p263)_第13张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第14张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第15张图片

注意这里实例化类的对象的方法!!!
注意:类的构造函数是在类实例化对象时自动调用!
(1) 注意实例化类对象写法!person p1(“Tom”, 13); 这一句就直接自动调用了类构造函数!
(2)实例化类对象也可以这样写:person p3 = person(“mike”, 15);

P175 模板-类模板与函数模板区别
黑马程序员C++视频笔记(第三部分p167-p263)_第16张图片
1、
黑马程序员C++视频笔记(第三部分p167-p263)_第17张图片
2、
黑马程序员C++视频笔记(第三部分p167-p263)_第18张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第19张图片
P176 模板-类模板中成员函数创建时机
黑马程序员C++视频笔记(第三部分p167-p263)_第20张图片
P177 模板-类模板对象做函数参数
黑马程序员C++视频笔记(第三部分p167-p263)_第21张图片
//定义一个模板类

黑马程序员C++视频笔记(第三部分p167-p263)_第22张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第23张图片
1、指定传入类型(最常用)
黑马程序员C++视频笔记(第三部分p167-p263)_第24张图片
2、参数模板化
黑马程序员C++视频笔记(第三部分p167-p263)_第25张图片
3、整个类模板化
黑马程序员C++视频笔记(第三部分p167-p263)_第26张图片
P178 模板-类模板与继承
黑马程序员C++视频笔记(第三部分p167-p263)_第27张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第28张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第29张图片
P17913 模板-类模板成员函数类外实现

首先要了解类成员函数的类外实现概念:
引入内联函数的目的是为了解决程序中函数调用的效率问题。 函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。
  在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数体中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。
  在程序中,调用其函数时,该函数在编译时被替代,而不是像一般函数那样是在运行时被调用。
  在类的内部对成员函数作声明,而在类体外定义成员函数,这是程序设计的一种良好习惯。如果一个函数,其函数体只有2-3行,一般可在声明类时在类体中定义。多于3行的函数,一般在类体内声明,在类外定义。
  .
  .
引用:https://blog.csdn.net/wangfei8348/article/details/51385203?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E7%B1%BB%E5%A4%96%E5%AE%9E%E7%8E%B0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-2-51385203

类成员函数实现包括两种:
(1)类成员函数的类外:
类成员函数的类外实现就是,在类内声明而在类外定义函数,但要注意,类外定义类的成员函数时要记得加 类名::-----作用域,否则就成了全局函数了,就不属于哪个类了!!!
(2)类成员函数的类内实现
即类成员函数声明和定义都在类内部!

黑马程序员C++视频笔记(第三部分p167-p263)_第30张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第31张图片
P180 模板-类模板分文件编写
黑马程序员C++视频笔记(第三部分p167-p263)_第32张图片

类分文件编写一般都是.h文件写类成员声明,在.cpp文件来具体实现!
(1)对于普通类,直接按上述份文件编写即可,直接包含头文件,编译时编译器根据包含的头文件去找对应的源文件,并把源文件中成员函数创建。
(2)对于模板类—存在一个问题,由于模板类成员函数是在调用时才创建的,所以编译时并没有创建,而调用时就导致无法识别!!----一般常用第二种方式—直接把类模板写在一个文件中不分文件编写!!!

小知识点:

黑马程序员C++视频笔记(第三部分p167-p263)_第33张图片
P118—120友元
黑马程序员C++视频笔记(第三部分p167-p263)_第34张图片1、
黑马程序员C++视频笔记(第三部分p167-p263)_第35张图片
2、
黑马程序员C++视频笔记(第三部分p167-p263)_第36张图片
3、
在这里插入图片描述

P181 模板-类模板与友元(不理解!!!)
黑马程序员C++视频笔记(第三部分p167-p263)_第37张图片

#include 

//2、全局函数配合友元  类外实现 - 先做函数模板声明,下方在做函数模板定义,在做友元
template<class T1, class T2> class Person;

//如果声明了函数模板,可以将实现写到后面,否则需要将实现体写到类的前面让编译器提前看到
//template void printPerson2(Person & p); 

template<class T1, class T2>
void printPerson2(Person<T1, T2> & p)//(1)注意:由于含有T1T2所以该函数也要写成模板形式所以要加上上面一句template-----单是注意:这样一来print person2函数的声明和实现就不是一套东西了(一个是普通函数声明,一个是模板函数实现,不配套,所以要改函数声明----很简单就是加一个<>)
{
	cout << "类外实现 ---- 姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;
}

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


	//全局函数配合友元  类外实现
	//friend void printPerson2(Person & p);//(1)错误!!!
	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", 30);
	printPerson2(p);
}

int main() {

	//test01();

	test02();

	system("pause");

	return 0;
}

(1)对普通类型函数声明加上“空模板参数列表(即<>)”便使其变成了模板函数声明,这样就与模板函数定义配套了!

注意:全局函数类内实现较常用!!!类外实现较复杂!

C++拷贝构造函数 深拷贝 浅拷贝
参考:https://blog.csdn.net/lwbeyond/article/details/6202256

=======================================================

.
P182—184暂搁置
.
.

=======================================================
P185----263 STL标准模板库学习

P185 STL初识-STL的基本概念
黑马程序员C++视频笔记(第三部分p167-p263)_第38张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第39张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第40张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第41张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第42张图片
黑马程序员C++视频笔记(第三部分p167-p263)_第43张图片

你可能感兴趣的:(黑马C++视频学习)