C++模板编程与泛型编程之类模板中的友元(二)

类模板中的友元:友元函数

  • 函数模板可以被声明为友元函数
template <typename U,typename V>
void func(U val1, V val2)
{
	cout << "val1 = " << val1 << endl;
	cout << "val2 = " << val2 << endl;

}
  • 调用:
func(2, 3);
func<float>(4.6f, 5); -- 第一个模板参数指定,第二个模板参数编译器自己推断
func<int, float>(4, 5.8f); -- 完全手工指定模板参数
  • 输出:
val1 = 2
val2 = 3
val1 = 4.6
val2 = 5
val1 = 4
val2 = 5.8

  • 增加Men类
class Men
{
private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};

template <typename U,typename V>
void func(U val1, V val2)
{
	Men mymen;
	mymen.funcmen(); 
}
  • 编译器报错,无法访问funcmen()函数。模板函数func不是Men的友元函数。

  • 让函数模板的某个实例成为友元函数
  • 代码行unc(2, 3);,会实例化出 void func<int,int>(int,int){......}
-- 函数模板func的声明
template <typename U, typename V> 	void func(U val1, V val2);

class Men
{
    friend void func<int, int>(int, int);  -- <int,int>是两个模板实参
   -- friend void func<>(int, int);    这种写法也可以
   -- friend void func<int>(int, int);  这种写法也可以

      friend void func<float,int>(float, int);
    --friend void func<>(float, int);

      friend void func<int, float>(int, float);
   -- friend void func<>(int, float);


private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};

template <typename U,typename V>
void func(U val1, V val2)
{
	Men mymen;
	mymen.funcmen(); 
}
  • 调用:
func(2, 3);
func<float>(4.6f, 5); 
func<int, float>(4, 5.8f)
  • 输出:
Men::funcmen被调用了
Men::funcmen被调用了
Men::funcmen被调用了

  • 让函数模板的某个实例成为友元函数:增加Men类模板
-- 函数模板func的声明
template <typename U, typename V> 	void func(U val1, V val2);

//Men类模板
template <typename Z>
class Men
{
    friend void func<int, int>(int, int);  -- <int,int>是两个模板实参
   -- friend void func<>(int, int);    这种写法也可以
   -- friend void func<int>(int, int);  这种写法也可以

      friend void func<float,int>(float, int);
    --friend void func<>(float, int);

      friend void func<int, float>(int, float);
   -- friend void func<>(int, float);


private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};

template <typename U,typename V>
void func(U val1, V val2)
{
	Men<int> mymen;
	mymen.funcmen(); 
}
  • 调用:
func(2, 3);
func<float>(4.6f, 5); 
func<int, float>(4, 5.8f)
  • 输出:
Men::funcmen被调用了
Men::funcmen被调用了
Men::funcmen被调用了

 


友元模板

-- Men类模板
template <typename Z>
class Men
{
    -- 让函数模板func成为类模板Men的友元函数模板
    template <typename U, typename V> friend void func(U val1, V val2);

private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};

template <typename U,typename V>
void func(U val1, V val2)
{
	Men<int> mymen;
	mymen.funcmen(); 
}
  • 将func函数模板(泛化版本)声明为Men类模板的友元模板之后,那么func函数模板的特化版本也会被看成是Men类模板的友元
//func全特化版本
template <>
void func(int val1, double val2)
{
	Men<int> mymen;
	mymen.funcmen();
}
  • 编译器会把全特化的func函数模板看待成一个实例化过的函数模板。

 


在类模板中定义友元函数

  • 这种友元函数是能够被调用的,而且也只有在代码中调用了函数的时候,编译器才会实例化出这个函数。
  • 之所以这样定义友元函数,一般都是因为在该友元函数中会 用到这个类模板。
  • 这种友元函数的调用与调用普通函数函数,就把他当成普通函数来看待即可。
//Men类模板
template <typename Z>
class Men
{
	friend void func2(Men<Z>& tmpmen)
	{
			tmpmen.funcmen();
	}
private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};
  • 调用:
Men<double> mymen2;
func2(mymen2);     -- 直接调用Men类模板中定义的友元函数func2

Men<int> mymen3;
func2(mymen3);
  • func2在Men类模板被实例化时并不会被一并实例化出来,只有调用了func2的时候,才会被实例化出来
  • 因为func2在类模板Men,所以调用func2时,如果func2中的代码特别简单,则func2会被当成内联函数来处理
  • 如果func2中的代码比较复杂,比如出现了for循环,那么func2很可能就不会被当做内联函数来处理。
//Men类模板
template <typename Z>
class Men
{
	friend void func2(Men<Z>& tmpmen)
	{
	for(int i= 0; i<1 ; ++i)	
           tmpmen.funcmen();
	}
private:
	void funcmen() const
	{
		cout << "Men::funcmen被调用了" << endl;
	}
};
  • func2(mymen2); 可以被实例化出  void func2(class Men<double>&);
  • func2(mymen3); 可以被实例化出  void func2(class Men<int>&);
  • func2其实是个全局函数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值