C++ 语言学习 day08 类模板对象,模板类继承,类模板友元函数,

一、  类模板对象当做函数的参数
     //第一种方式,直接传入模板对象
void fun(person<string,int>& per)

//类模板传入方式
template <class T1,class T2>
void fun3(person<T1,T2>& per)

//整个类模板化
template <class T>
void fun4(T& per)


二、类模板继承
    普通类继承:class son:public father{}
     模板类继承:普通子类继承模板类;
     格式:class 子类:public 父类<指定类型>
     构建对象:和普通对象的构建一样 类名 对象(参数列表);
 
   类模板继承类模板
   格式: template<class T1,class T2>
              class son: public person<T1,T2> {}


三、类模板成员函数类外实现
   在类模板中,函数的声明和定义都应该在h文件或者在mian的cpp中,在类中声明,在类外定义需要加上模板的类限定符
    案例:template <class T1,class T2>
              class myson :public person<T1, T2>
              {public:int display(T1 x);};
            //;类内声明 类外实现(模板类成员函数)
             template <class T1,class T2>
            int myson<T1, T2>::display(T1 x){}    
          }
    小秘密:一般情况下会把定义模板类的文件后缀修改成.hpp的形式。


4.代码:

头文件

#pragma once
#include <iostream>
using namespace std;
template <class T1,class T2>
class person
{
public:
	T1 m_name;
	T2 m_age;
	person(T1 name = "", T2 age = 0)
	{
		this->m_name = name;
		this->m_age = age;
		cout << "我是构造" << endl;
	}
	void personShow()
	{
		cout << "我是person的show函数" << endl;
	}
};

//普通类继承模板类
class son :public person<string, int>
{
public://如果父类真的没有缺省构造,应该怎么办
	son(int x):person("10",x)
	{
		cout << "我是son的构造函数" << endl;
	}
	void  show()
	{
		cout << "我是son的show()" << endl;
	}
};

template <class T1,class T2>
class myson :public person<T1, T2>
{
public:
	T1 myname;
	myson():person<T1,T2>("1",1)
	{
		cout << "我是myso的构造" << endl;
	}
	~myson()
	{
		cout << "我是myso的析构" << endl;
	}
	myson(const myson<T1, T2>& s)
	{
		cout << "我是myso的拷贝构造" << endl;
	}
	void myshow()
	{
		//m_name怎么使用才能可以
		cout << "我的name = " << myname << "父类的name=" << this->m_name << endl;
	}
	int display(T1 x);
};
//;类内声明 类外实现(模板类成员函数)
template <class T1,class T2>
int myson<T1, T2>::display(T1 x)
{
	cout << "myson<T1, T2>::myname=" << myname << endl;
	return 0;
}

.cpp 文件

#include <iostream>
#include "person.h"
#include <string>
using namespace std;
//第一种方式,直接传入模板对象
void fun(person<string, int>& per)
{
	per.personShow();
}
//类模板传入方式
template <class T1,class T2>
void fun3(person<T1,T2>& per)
{
	per.personShow();
	//在函数调用的时候,想看一下传入的T1和T2到底是什么类型
	cout << typeid(T1).name() << " " << typeid(T2).name() << endl;
}
//整个类模板化
template <class T>
void fun4(T& per)
{
	per.personShow();
	cout << typeid(T).name() << endl;
}
int main()
{
	person<string,int> danny("danny",10);
	//fun(danny);
	//fun3(danny);
	//需要传入类模板的类型参数string和int
	//fun4<person<string,int>>(danny);
	//子类继承模板类案例
	//son s;
//	s.show();
	person<string, int > x("dd", 10);
	myson<string, int> my;
	my.myshow();
	my.display("ad");
	cout << "hello" << endl;
}

四、 类模板的友元函数
       1.类外实现友元函数:
           先需要在类内声明函数,声明的时候需要加空模板列表,也就是函数名后<>
           其次需要在类外实现,但一定是类的定义前实现,在friend函数声明前需要有函数体。
           最后在定义完友元函数后,需要先声明模板类。

       2.类内实现模板类的友元函数,和普通友元函数实现一样。

代码:

#include <iostream>
//#include "person.hpp"
using namespace  std;
//小番茄:提示工具 vs;

template <class T> class person;
template <class T>
void display1(person<T>& per) {}//类前定义

template <class T>
class person
{
	T age;
public:
	friend void show(person<T>& per) {
		per.age = 123;
		cout << "per.age = " << per.age << endl;
	}
	//需要加空模板的参数列表,必须加尖括号
	friend void display1<>(person<T>& per);
};

int main()
{
    person<int> per;
    show(per);
    display1(per);
    return 0;  
}
//stl  vector   set  list  deque  map  c++11标准

   练习:实现一个通用的数组类 ( )
          第一点:他需要支持基本数据类型和自定义类型。t* parr,int size,int cap)  cap是容量,已经存了多少元素。如果存了6个则cap=6
           第二点:通用数组中的数据要放入堆内存(new),需要提供
           第三点:需要实现构造 析构 有参构造函数
           第四点:需要实现==运算符重载,下标运算符[]重载。
          第五点:提供两个函数,可以给数组进行为插和尾删除。

代码:

头文件:

#pragma once
#include <iostream>
#include <cstring>
#include <cstdbool>
using namespace std;
template<class T>
class arr
{
public:
	arr();//无参构造
	arr(int size)//有参构造
	{
		this->size = size;
		this->cap = 0;
		this->parr = new T[this->size];//开辟空间
		memset(parr, 0, sizeof(T) * size);//初始化数组
	}
	~arr();//析构函数
	void operator=(const arr& other)//重载运算符号 = 
	{
		this->cap = other.cap;
		this->size = other.size;
		if (this->parr != NULL)
		{
			delete[] parr;
		}
		this->parr = new T[this->size];
		memcpy(parr, other.parr, sizeof(T) * size);//内存传输
		//this->parr = other.parr;  错误
		//for (int i = 0;i < other.cap; ++i)
		//{
		//	this->parr[i] = other.parr[i];
		//}
	}
	bool operator==(const arr& other)//重载运算符号 ==
	{
		if (this->size == other.size && this->cap == other.cap)//看他们的元素个数,和存储空间是否相等
		{
			return true;
		}
		return false;
	}
	T& operator[](const int size)//重载运算符号 []
	{
		if (size > this->cap)
		{
			return parr[0];
		}
		return parr[size];
	}
	void push_back(const T& temp);//尾部添加函数
	void pop_back();//尾部删除函数
private:
	T* parr;   //数组的首地址
	int size; //整个数组的元素个数
	int cap;  //数组中已经存了多少元素了


};
template<class T>
arr<T>::arr()//类外实现无参构造
{
	this->size = 10;
	this->cap = 0;
	this->parr = new T[this->size];//开辟空间
	
}

template<class T>
arr<T>::~arr()//类外实现析构函数
{

}

template<class T>
void arr<T>::push_back(const T& temp) //添加元素的函数
{
	if (cap == size)
	{
		return;
	}
	parr[++cap] = temp;// cap ++  和元素存储到数组
}
template<class T>
void  arr<T>::pop_back()//直接存储元素的数量 减  1
{
	if (cap > 0)
	{
		cap--;
	}
}

.cpp 文件


#include <iostream>
#include "arr.hpp"
void show(arr<int> myarr)//arr 类型的数  myarr
{
    for (int j = 0; j < 7;++j)
    {
        cout << myarr[j] << "  ";//重载了, 运算符 []  ,所以可以这样!使用
    }
    cout << endl;
}
void fun1()
{
    arr<int> myarr(10);
    for (int i = 0;i < 5;++i)
    {
        myarr.push_back(i);
    }
   // myarr[1] = 0;
    show(myarr);
    arr<int> youarr;
    youarr = myarr;
    show(youarr);
   // cout <<
    youarr.pop_back();
    show(youarr);

}

int main()
{
    fun1();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值