day8-11 类模板碰到友元函数-类外实现(注意点有点多)

代码

#define _CRT_SECURE_NO_WARNINGS
#include
#include 
using namespace std;

//让编译器提前看到printPerson声明
//让编译器看到Person类声明
template<class T1, class T2> class Person;
template<class T1, class T2>void printPerson(Person<T1, T2> & p);


template<class T1, class T2>
class Person
{
	//友元函数类内实现  利用空参数列表 <> 来告诉编译器 模板函数的声明
	friend void printPerson<>(Person<T1, T2> & p); //普通函数 声明
	/*{
		cout << "姓名:" << p.m_Name << "  年龄: " << p.m_Age << endl;
	}*/
public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

private:
	T1 m_Name;
	T2 m_Age;
};

//类外实现,模板函数的实现
template<class T1 ,class T2>
void printPerson(Person<T1, T2> & p)
{
	cout << "姓名:" << p.m_Name << "  年龄: " << p.m_Age << endl;
}

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


int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

代码解析

  • 一、在类内声明友元函数的时候,friend void printPerson (Person & p);表示这个函数至少一个普通函数,因为模板函数或者模板类都是紧跟template后面;所以需要让编译器强行知道这是一个模板函数的声明就需要利用空参数列表 <> 来告诉编译器 模板函数的声明,friend void printPerson<>(Person & p); -------最终答案。
  • 二、接着第一个问题看,test01printPerson(p);如果普通函数和模板函数都能匹配到printPerson函数的话是会优先调用普通函数,在没有利用空列表来声明时,把friend void printPerson (Person & p);当做普通函数调用,但是却找不到普通函数的实现,虽然printPerson在类外实现,但是类外实现属于模板函数的实现,所以会出错。
  • 三、下面为函数模板与普通函数的区别以及调用规则,第二个注释就是我们用到的。
  //1 、如果出现重载  优先使用普通函数调用,如果没有实现,出现错误
	//myPrint(a, b);

	//2、 如果想强制调用模板 ,那么可以使用空参数列表
	myPrint<>(a, b);

	//3、 函数模板可以发生重载
	int c = 30;
	myPrint(a, b, c);

	//4、 如果函数模板可以产生更好的匹配,那么优先调用函数模板
	char c1 = 'c';
	char d = 'd';
	myPrint(c1, d);
  • 四、因为friend void printPerson<>(Person & p);类模板中成员函数 一开始不会创建出来,而是在运行时才去创建,所以在类内声明,编译器刚开始是看不到的,所以需要在外部声明一下
//让编译器提前看到printPerson声明
//让编译器看到Person类声明
template<class T1, class T2> class Person;
template<class T1, class T2>void printPerson(Person<T1, T2> & p);  
  • 五、总结
    day8-11 类模板碰到友元函数-类外实现(注意点有点多)_第1张图片

你可能感兴趣的:(c++基础学习,c++,c语言,编译器)