friend 不仅仅可以作为友元

friend是C++中封装的漏网之鱼。

C++中的friend允许另外的类或者是函数访问本类的任何成员,甚至是private成员,只要该类声明其为友元。

可是,在有些情况下,并不是允许外界访问类的内部实现而使用友元。这就是在 “模板定义” 与 “类型转换” 之间的一个trick了。

首先,看一个简单的有理数的模板类,该类定义了有理数,并且实现有理数的乘法。

注:下述代码中,将operator*声明为非成员函数,是因为

“如果你需要对成员函数所有的参数(所有的,当然也就包括this指针啦)进行类型转换,那么将该函数声明为非成员函数”。

这对C++模板类同样适用。

在上述代码中,重载了 * 符号,用于计算两个有理数之间的乘法。

一个自然而然的道理,如果我们需要支持 有理数 * 自然数 ,这是一个无可厚非的要求。当我们才有下面的调用

Rational<int> a = Rational(1,2);

Rational<int> ret = a * 2;

编译不通过,在非模板类中这是很正常的事,可是在模板类中却出现了问题.

下面一一进行分析:

当编译器看到operator*的调用的时候,编译器不知道我们调用哪个函数,编译器看到这个模板函数时,第一要做的就是将该

函数实例化出来,也就是要首先推断出T的类型,但是几经周折,发现不行。

首先,为了推导出T,编译器对 * 调用的两个参数进行入手,分别为 Rational<int>   和 int, 由第一个参数可以得到 T

为int, 但是在第二个实参呢,编译器怎么推断 T 的类型。 你也许会说,此时编译器就应该使用 Rational<int> 的隐式构造函数

啊。不就可以 推导出 T 的类型了吗。 但是,编译器绝不会这么做,因为在 模板实参  的推导过程当中是不会 考虑隐式转换的。

这是本文最重要的一句话。

因此,在面对这样的 实参推导 的问题是,friend 变出场了,由于 friend 可以在  模板类 中指明某个特定的函数,也就是说,

在函数调用之前,声明该函数,那么在函数调用时,相应的类模板 就不再需要 依赖于 模板实参的推导了,而只需要对这个

友元函数进行参数推导即可。

因此将operator * 声明为该类的友元。

但是,还有一个问题,便是链接时的问题了,只在类定义体中声明该函数,如果不定义的话,连接器便会发出抱怨,找不到

定义体(这里没看懂。需要仔细斟酌。)

因此,将 operator* 声明为友元函数并且将实现定义在类中。

于是,在类模板定义时,出现了同样的话,如果  在编写一个类模板的时候,而 该类的与模板相关的函数  需要支持函数参数隐式转换的时候,将该函数定义为模板类类中的friend函数。

friend 不仅仅可以作为友元

时间: 2024-10-29 19:07:47

friend 不仅仅可以作为友元的相关文章

阻止继承的思路,屏蔽友元类

来自万一:http://www.cnblogs.com/del/archive/2008/01/16/1041446.html --------------------------------------------------------------------------------------- //下面说的数据成员不仅仅指方法 TMyClass = class(TObject)   function Fun1: string; {公共区域的数据成员在默认状态下会归于 published

模板类的友元重载

模板类的友元重载和普通类的友元重载有不同之处,可以参考这篇CSDN博客http://blog.csdn.net/ozwarld/article/details/7770808 #include <iostream> using namespace std; template <class T> class Test; // 模板类前置声明 template<class T> ostream& operator << (ostream& out

c++类模板之间友元函数调用

1 #include <stdio.h> 2 #include <iostream> 3 4 using namespace std; 5 6 template<typename T> class BTree; 7 8 /***************************节点类模板*********************************/ 9 template<typename T> 10 class BTreeNode{ 11 friend

C++ 友元函数总结

1.为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率 具体来说:为了使其他类的成员函数直接访问该类的私有变量 即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数 优点:能够提高效率,表达简单.清晰 缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数. 2.什么时候使用友元函数: 1)运算符重载的某些场合需要使用友元. 2)两个类要共享数据的时候 3.怎么使用友元函数: 友元函数的参数: 因为友元函数没有this指针,则

c++的友元类、方法及其益处

在java中,我们知道除了public和private,protected外,还有默认的包可见性访问级别,虽然如此,很多时候出于早期设计缺陷的原因,我们需要访问一些包或者protected可见性级别的方法,这个时候就比较麻烦了,要是选择和目标服务在相同包中,总看起来很奇怪,如果作为子类继承,则更加奇怪.但是我们又不想把该接口服务的可见性声明为public. c++中,这一点做的就比较好,我们知道在c++中,有友元类.方法的特性,该特性相当于白名单的作用,当一个类或者成员函数.非OO函数被声明为目

c++ 中的友元函数的普通用法

C++中友元函数的调用,一般分为三种方式: 1.一般的友元函数 2.类A作为类B的友元类,则类A的成员函数都是类B的友元函数. 3.一个类的成员函数作为另外一个类的友元函数 //分为友元函数的例子 类A 作为测试的类,类B 是类A的友元类.class A{public: A() {  a = 100;  b = 10; } friend class B; //这儿公私均可,常常用到的是变为私有变量,类B是类A的友元类.友元的第二种方式,需要带class int getA() {  return

C++友元函数

1. 1 #include <iostream> 2 using namespace std; 3 4 class Time{ 5 friend void func(Time &t); // 声明全局函数为一个友元函数 6 public: 7 Time(int h, int m, int s) : i_mHour(h), i_mMin(m), i_mSecon(s) { } // 构造函数 8 private: 9 int i_mHour; 10 int i_mMin; 11 int

模板类的约束模板友元函数:template friend functions

本来这篇博客是不打算写的,内容不是很难,对于我自己来讲,更多的是为了突出细节. 所谓template friend functions,就是使友元函数本身成为模板.基本步骤:1,在类定义的前面声明每个模板函数.eg:template <typename T> void counts(); template <typename T> void report<>(T &);2,在类声明中再次将模板声明为友元. template <typename TT>

C++ 类模板二(类模版与友元函数)

//类模版与友元函数 #include<iostream> using namespace std; template<typename T> class Complex{ public: Complex(T a,T b); void Print() const//const修饰的是this指针 { cout << this->Real << ":" <<this->Image<< endl; } /*