当一个类包含一个友元声明时,类与友元各自是否是模板是相互无关的。如果一个类模板包含一个非模板友元,则友元被授权可以访问所有模板实例。如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。

1. 一对一友好关系

  类模板与另一个(类或函数)模板间友好关系的最常见形式是建立对应实例及其友元间的友好关系。例如,我们的 Blob 类应该讲 BlobPtr 类和一个模板版本的 Blob 相等运算符定义为友元。

  为了引用(类或函数) 模板的一个特定实例,我们必须首先声明模板自身。一个模板声明包括模板参数列表:

//前置声明,在 Blob 中声明友元所需要的
template <typename> class BlobPtr;
template <typename> class Blob; //运算符==中的参数所需要的
template <typename T>
bool operator == (const Blob<T>&, const Blob<T>&); template <typename T>
class Blob {
//每个Blob实例将访问权限授予用相同类型实例化的BlobPtr和相等运算符
friend class BlobPtr<T>;
friend bool operator ==<T> (const Blob<T>&, const Blob<T>&);
};

  我们首先将Blob、BlobPtr和Operator== 声明为模板。这些声明时 operator==函数的参数声明以及 Blob 中的友元声明所需要的。

  友元的声明用 Blob 的模板形参作为它们自己的模板形参。因此,友好关系被限定在用相同类型实例化的 Blob 与 BlobPtr 相等运算符之间:

Blob<char> ca;    //BlobPtr<char>和 operator==<char>都是本对象的友元
Blob<int> ia; //BlobPtr<int>和 operator==<int>都是本对象的友元

BlobPtr<char>的成员可以访问 ca (或任何其他 Blob<char>对象)的非 Public 部分,但 ca 对 ia (或任何其他 Blob<int> 对象) 或 Blob 的任何其他实例都没有特殊访问权。

2. 通用和特定的模板友好声明

//前置声明,在将模板的一个特定实例声明为友元时要用到
template<typename T> class Pal; class C { //C 是一个普通的非模板类
friend class Pal<C>; //用类C 实例化的Pal是C 的一个友元
template <typename T> friend class Pal2; //Pal2 的所有实例都是C 的友元;这种情况无须前置声明
}; template <typename T> class C2 {//C2 本身是一个模板类
// C2 的每个实例将相同实例化的 Pal 声明为友元
friend class Pal<T>; // Pal 的模板声明必须在作用域内 // Pal2 的所有实例都是 C2 的每个实例的友元,不需要前置声明
template <typename X> friend class Pal2; // Pal3 是一个模板类,它是 C2 所有实例的友元
friend class Pal3; //不需要 Pal3 的前置声明
};

  为了让所有实例成为友元,友元声明中必须使用与模板本身不同的模板参数。

C++学习笔记(2)----类模板和友元的更多相关文章

  1. C++学习笔记36:类模板

    类模板的目的 设计通用的类型式,以适应广泛的成员数据型式 类模板的定义格式 template<模板形式参数列表>class 类名称{...}; 原型:template<typenam ...

  2. C++学习笔记(3)----类模板的static成员

    与任何其他类相同,类模板可以声明 static 成员: template <typename T> class Foo { public: static std::size_t count ...

  3. C++ Primer 学习笔记_53_类和数据抽象 --友元、static员

    分类 --友元.static成员 一.友元 友元机制同意一个类将对其.友元关系:一个样例 如果一个窗体管理类Window_Mgr可能须要訪问由其管理的Screen对象的内部数据.Screen应该同意其 ...

  4. Java学习笔记之---类和对象

    Java学习笔记之---类和对象 (一)类 类是一个模板,它描述一类对象的行为和状态  例如:动物类是一个类,动物们都有属性:颜色,动物们都有行为:吃饭 public class Dog { Stri ...

  5. Java学习笔记——File类之文件管理和读写操作、下载图片

    Java学习笔记——File类之文件管理和读写操作.下载图片 File类的总结: 1.文件和文件夹的创建 2.文件的读取 3.文件的写入 4.文件的复制(字符流.字节流.处理流) 5.以图片地址下载图 ...

  6. python学习笔记4_类和更抽象

    python学习笔记4_类和更抽象 一.对象 class 对象主要有三个特性,继承.封装.多态.python的核心. 1.多态.封装.继承 多态,就算不知道变量所引用的类型,还是可以操作对象,根据类型 ...

  7. 微信小程序开发:学习笔记[2]——WXML模板

    微信小程序开发:学习笔记[2]——WXML模板 快速开始 介绍 WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件.事件系统,可以构建 ...

  8. UML学习笔记:类图

    UML学习笔记:类图 有些问题,不去解决,就永远都是问题! 类图 类图(Class Diagrame)是描述类.接口以及它们之间关系的图,用来显示系统中各个类的静态结构. 类图包含2种元素:类.接口, ...

  9. c++类模板之友元函数

    前言:自从开始学模板了后,小编在练习的过程中.常常一编译之后出现几十个错误,而且还是那种看都看不懂那种(此刻只想一句MMP).于是写了便写了类模板友元函数的用法这篇博客.来记录一下自己的学习. 普通友 ...

随机推荐

  1. abp angular 前端权限控制

    import { AppComponentBase } from '@shared/app-component-base'; this.permission.isGranted(menuItem.pe ...

  2. JavaScript《一》

    脚本语言概念:不需要提前编译的,即时执行的语言,如js,t-sql等 在一个js块中,只要有一个语句出现错误,整个块都不执行 强类型:在编译时就已经确定的类型,弱类型,在运行时,编译器自动根据赋值在确 ...

  3. (7.0 version)当销售单中包含service或phantom类型的产品时,销售单不能完成的原因分析及解决方案

    首先说一下service类型的产品,由于该类型的产品不需要发货,所以当在销售订单确认了后,销售单直接变成了等待开票的状态,但当开票的流程结束后,订单却还是停在销售单的状态上,该问题的解决方案是安装Ta ...

  4. Mac下包管理平台homebrew的使用

    一.安装 参考:http://www.cnblogs.com/EasonJim/p/6287098.html 二.使用 假设我要安装node,命令如下: 安装软件 brew install node ...

  5. Linux网络编程服务器模型选择之并发服务器(下)

    前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接, ...

  6. How can I set ccshared=-fPIC while executing ./configure?

    解决方式如下: make clean ./configure CFLAGS=-fPIC CXXFLAGS=-fPIC

  7. Linux防火墙简介 – iptables配置策略

    Linux防火墙简介 – iptables配置策略 Netfilter/iptables简介 要想真正掌握Linux防火墙体系,首先要搞清楚Netfilter和iptables的关系,Netfilte ...

  8. JVM的类加载时机

    类加载过程中每个步骤的顺序 我们已经知道,类加载的过程包括:加载.连接.初始化,连接又分为:验证.准备.解析,所以说类加载一共分为5步:加载.验证.准备.解析.初始化. 其中加载.验证.准备.初始化的 ...

  9. R语言中apply函数

    前言 刚开始接触R语言时,会听到各种的R语言使用技巧,其中最重要的一条就是不要用循环,效率特别低,要用向量计算代替循环计算. 那么,这是为什么呢?原因在于R的循环操作for和while,都是基于R语言 ...

  10. SQL:存储过程

    1/什么是存储过程及概念 Transact-SQL中的存储过程,非常类似于.Net语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可 ...