纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。
类模板与友元函数
模板类的友元函数有三类:
- 1)非模板友元函数:友元函数不是模板函数,而是利用模板类参数生成的函数。
- 2)约束模板友元函数:模板类实例化时,每个实例化的类对应一个友元函数。
- 3)非约束模板友元函数:模板类实例化时,如果实例化了n个类,也会实例化n个友元函数,每个实例化的类都拥有n个友元函数。
1️⃣非模板友元函数
非模板友元函数就是将一个普通函数声明为友元函数。我们先来看一段代码:
#include <iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class Maker
{
private:
T1 m_x;
T2 m_y;
public:
Maker(const T1 x, const T2 y) : m_x(x), m_y(y) {
}
};
Maker<string,int> m1("感谢支持强风吹拂king的博客",666);
void show()
{
cout << "x = " << m1.m_x << ", y = " << m1.m_y << endl;
}
int main()
{
show();
}
📝解释:
Maker是模板类,有两个模板参数T1,T2,在模板Maker类中用T1和T2分别定义了m_x,和m_y,构造函数使用初始化列表给m_x,和m_y赋值。
用模板类Maker定义全局对象m1,再定义全局函数show(),在全局函数show()中访问模板类Maker的私有成员,看下面运行结果(报错):
如果我们把全局函数show(),给声明成模板Maker的友元函数可以访问Maker的私有成员吗?
friend void show();
🖲执行结果如下:
在类模板Maker中,将普通函数show()函数声明为友元函数,则show()函数是类模板Maker所有实例的友元函数。例如,它是Maker<string,int>,Maker<string,int>,Maker<string,double>等的友元函数。
这种为类模板设置友元函数的方法在语法上没有任何错误,但是要用模板类去创建全局对象,代码这么写实在是太笨了,在学习友元的时候,如果Maker是普通类,我们可以把Maker普通类的引用传给友元函数而不必创建全局对象。
那么Maker是类模板,可以这么写吗?答案是不可以。Maker只是类的通用描述,根本不存在类名叫Maker的类,但是你具体化函数模板,也就是后面加上参数列表<具体的数据类型>,这就可以当做一个具体的类,就可以像普通类一样使用。
#include <iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class Maker
{
private:
T1 m_x;
T2 m_y;
public:
Maker(const T1 x, const T2 y) : m_x(x), m_y(y) {
}
friend void show(const Maker<string, int>& a);
};
void show(const Maker<string, int>& a)
{
cout << "x = " << a.m_x << ", y = " << a.m_y << endl;
}
int main()
{
Maker<string,int> m1("感谢支持强风吹拂king的博客",777);
show(m1);
return 0;
}
🖲执行结果如下:
如果main函数内部我们这样写,编译器会报错吗?
int main()
{
Maker<char,int> m1('k',666);
show(m1)