剖析C++编程中friend关键字所修饰的友元函数和友元类

在某些情况下,为不是类成员的函数或单独类中的所有函数授予成员级别的访问权会更方便。仅类实现器可以声明其友元。函数或类不能将其自身声明为任何类的友元。在类声明中,使用 friend 关键字和非成员函数名称或其他类,以允许其访问你的类的专用和受保护成员。
语法

  friend class-name;
friend function-declarator;

友元声明
如果声明以前未声明的友元函数,则该函数将被导出到封闭非类范围。
友元声明中声明的函数被视为已使用 extern 关键字声明。(有关 extern 的详细信息,请参阅静态存储类说明符。)
尽管具有全局范围的函数可以在其原型之前声明为友元函数,但是成员函数在它们的完整类声明出现前不能声明为友元函数。以下代码演示此失败的原因:

class ForwardDeclared; // Class name is known.
class HasFriends
{
 friend int ForwardDeclared::IsAFriend(); // C2039 error expected
};

前面的示例将类名 ForwardDeclared 输入到范围中,但是完整的声明(具体而言,声明函数 IsAFriend 的部分)是未知的。因此,friend 类中的 HasFriends 声明会生成一个错误。
若要声明两个互为友元的类,则必须将整个第二个类指定为第一个类的友元。此限制的原因是该编译器仅在声明第二个类的位置有足够的信息来声明各个友元函数。
注意
尽管整个第二个类必须是第一个类的友元,但是可以选择将第一个类中的哪些函数作为第二个类的友元。
友元函数
friend 函数是一个不为类成员的函数,但它可以访问类的私有和受保护的成员。友元函数不被视为类成员;它们是获得了特殊访问权限的普通外部函数。友元不在类的范围内,除非它们是另一个类的成员,否则不会使用成员选择运算符(. 和 –>)调用它们。 friend 函数由授予访问权限的类声明。可将 friend 声明放置在类声明中的任何位置。它不受访问控制关键字的影响。
以下示例显示 Point 类和友元函数 ChangePrivate。 friend 函数可以访问其接受为参数的 Point 对象的私有数据成员。

// friend_functions.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class Point
{
 friend void ChangePrivate( Point & );
public:
 Point( void ) : m_i(0) {}
 void PrintPrivate( void ){cout << m_i << endl; }

private:
 int m_i;
};

void ChangePrivate ( Point &i ) { i.m_i++; }

int main()
{
 Point sPoint;
 sPoint.PrintPrivate();
 ChangePrivate(sPoint);
 sPoint.PrintPrivate();
// Output: 0
   1
}

作为友元的类成员
类成员函数可以声明为其他类中的友元。请看下面的示例:

// classes_as_friends1.cpp
// compile with: /c
class B;
class A {
public:
 int Func1( B& b );
private:
 int Func2( B& b );
};
class B {
private:
 int _b;
 // A::Func1 is a friend function to class B
 // so A::Func1 has access to all members of B
 friend int A::Func1( B& );
};
int A::Func1( B& b ) { return b._b; } // OK
int A::Func2( B& b ) { return b._b; } // C2248

在前面的示例中,仅为函数 A::Func1( B& ) 授予对类 B 的友元访问权限。因此,访问私有成员 _b 在类 Func1 的 A 中是正确的,但在 Func2 中是不正确的。
friend 类是其所有成员函数都是类的友元函数的类,即,其成员函数具有对类的私有成员和受保护成员访问权限。假定类 friend 中的 B 声明是:

friend class A;

在这种情况下,将为类 A 中所有成员函数授予对类 B 的友元访问权限。以下代码是友元类的示例:

// classes_as_friends2.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class YourClass {
friend class YourOtherClass; // Declare a friend class
public:
 YourClass() : topSecret(0){}
 void printMember() { cout << topSecret << endl; }
private:
 int topSecret;
};

class YourOtherClass {
public:
 void change( YourClass& yc, int x ){yc.topSecret = x;}
};

int main() {
 YourClass yc1;
 YourOtherClass yoc1;
 yc1.printMember();
 yoc1.change( yc1, 5 );
 yc1.printMember();
}

友元关系不是相互的,除非如此显式指定。在上面的示例中,YourClass 的成员函数无法访问 YourOtherClass 的私有成员。
托管类型不能具有任何友元函数、友元类或友元接口。
友元关系不能继承,这意味着从 YourOtherClass 派生的类不能访问 YourClass 的私有成员。友元关系不可传递,因此 YourOtherClass 的友元类无法访问 YourClass 的私有成员。
下图显示了 4 个类声明:Base、Derived、aFriend 和 anotherFriend。只有类 aFriend 具有对 Base 的私有成员(以及对 Base 可能已继承的所有成员)的直接访问权限。

内联友元定义
可以在类声明中定义友元函数。这些函数是内联函数,类似于成员内联函数,其行为就像它们在所有类成员显示后但在类范围关闭前(类声明的结尾)被定义时的行为一样。
类声明中定义的友元函数不被认为在封闭类的范围内;它们在文件范围内。

(0)

相关推荐

  • 简要介绍C++编程中的友元函数和友元类

    一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来补充介绍一个例外--友元(friend). fnend 的意思是朋友,或者说是好友,与好友的关系显然要比一般人亲密一些.有的家庭可能会这样处理:客厅对所有来客开放,而卧室除了本家庭的成员可以进人以外,还允许好朋友进入.在C++中,这种关系以关键宇 friend 声明,中文多译为友元.友元可以访问与其有好友关系的类

  • 解析C++中不能重载为友元函数的四个运算符

    C++规定有四个运算符 =, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数),这是为什么呢?现在先说说赋值运算符"="的重载C++规定赋值运算符"="只能重载为类的非静态成员函数,而不可以重载为类的友元函数.不能重载为类的静态成员应该比较容易理解,因为静态成员函数是属于整个类的,不是属于某个对象的,它只能去操作类静态数据成员.而赋值运算符"="是基于对象操作的.那么为什么赋值运算符不可以重载为类的友元函数?像同样都是双目

  • c++友元函数与友元类的深入解析

    友元函数和友元类的需要:类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性.另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率. 为了解决上述问题,提出一种使用友元的方案.友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面

  • C++中的friend友元函数详细解析

    友元函数是可以直接访问类的私有成员的非成员函数.它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend. 我们已知道类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性.另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运

  • C++友元(Friend)用法实例简介

    相对于Java而言,友元是C++中特有的一种元素,很多教材上对其介绍的相对较少,因此初学的时候往往不能很快掌握,本文总结了友元的用法和一些注意的地方,供大家参考借鉴.希望能对初学C++的朋友起到一点帮助作用. 操作步骤: 1)在MyFriend类中,将Father类定义成友元 2)写一个Son类继承自Father类 3)在Father类和Son类的构造函数中分别创建MyFriend对象,并定义其内部的三个变量 4)在MyFriend类的构造函数中创建Father对象,并定义其内部的三个变量 结果

  • C++之友元:友元函数和友元类详解

    一.友元介绍我们知道,类的成员函数可以访问同类的其他成员函数,包括公有.私有和保护成员.而类的外部函数只能访问类的公有成员. 友元是一种允许非类成员函数访问类的非公有成员的一种机制.可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元. 友元函数友元类 二.友元函数友元函数在类作用域外定义,但它需要在类体中进行说明为了与该类的成员函数加以区别,定义的方式是在类中用关键字friend说明该函数,格式如下: friend  类型 友元函数名(参数表);友元的作用在于提高程序的运行效率 友

  • C++运算符重载 成员函数与友元函数详解

    复制代码 代码如下: #include<iostream>using namespace std;class A{    int x,y;    public:    A(int xx,int yy):x(xx),y(yy){}    A(){x=0;y=0;}    A operator+(const A&b) //不加const限定,也可以    { return A(x+b.x,y+b.y); }    A operator-()    { return A(-x,-y); } 

  • 关于C++中的友元函数的一些总结

    1.友元函数的简单介绍 1.1为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率.如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数.具体来说:为了使其他类的成员函数直接访问该类的私有变量.即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数. 实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元.(2)两个类要共享数据的时候. 1.2使用友元函数的优缺点 1.2.1优点:能够

  • C++友元函数与拷贝构造函数详解

    一.友元函数 1.友元函数概述: (1)友元函数是定义在一个类外的普通函数. 友元函数和普通函数的定义一样;在类内必须将该普通函数声明为友元. (2)友元函数不是成员函数. 不能通过对象来调用,而是直接调用;友元函数可以访问类的公有.受保护以及私有成员,但是必须通过对象.对象指针或者对象引用来访问. 2.友元函数的声明: friend 返回值类型 函数名(参数表); 在类中只需要将这个声明放置在公有部分即可. class Point { double x, y; public: Point(){

  • 剖析C++编程中friend关键字所修饰的友元函数和友元类

    在某些情况下,为不是类成员的函数或单独类中的所有函数授予成员级别的访问权会更方便.仅类实现器可以声明其友元.函数或类不能将其自身声明为任何类的友元.在类声明中,使用 friend 关键字和非成员函数名称或其他类,以允许其访问你的类的专用和受保护成员. 语法 friend class-name; friend function-declarator; 友元声明 如果声明以前未声明的友元函数,则该函数将被导出到封闭非类范围. 友元声明中声明的函数被视为已使用 extern 关键字声明.(有关 ext

  • C++类中const修饰的成员函数及日期类小练习

    目录 一.const修饰类的成员函数 1.问题引出: 2.问题分析 3.const修饰类的成员函数 二. 类的两个默认的&运算符重载 三. 日期类小练习 总结 一.const修饰类的成员函数 1.问题引出: 给出一段简单的代码 代码段: #include <iostream> using std::cin; using std::cout; using std::endl; class Date1 { public: Date1(int year = 2000) 类的全缺省构造函数(可

  • C++ 中友元函数与友元类详解

    C++ 中友元函数与友元类详解 总的来说,友元分为两类:友元函数与友元类.友元是针对类而言,它提供了一种非类的成员函数来访问类的非公有成员的一种机制.可以把一个函数指定为某类的友元,这个函数称为这个类的友元函数.也可以将类A指定为类B的友元,则类A是类B的友元类,类A的所有成员函数均是类B的友元函数,均可以访问类B的非公有成员.        友元函数的注意事项: (1)友元函数不是类的成员函数,在函数体中访问对象的成员,必须用"对象名.对象成员"方式来访问, 友元函数可以访问类中的所

  • C++中的友元函数与友元类详情

    目录 一.问题背景 二.友元函数 三.友元类 一.问题背景 对类的封装是C++三大特性中的一个重要特性,封装好的数据在类的外部是访问不到的但是一旦出了问题,想要操作被封装的数据怎么办呢?由此友元函数友元类诞生了.在类中用friend关键字声明的函数或类,可以对类体中的任何权限成员属性进行操作有好处就有坏处友元函数.友元类严重破坏类的封装性,不到迫不得已不要使用. 二.友元函数 声明部分: friend 返回类型 函数名 (参数列表); 定义部分:返回类型 函数名 (参数列表){        函

  • Java多线程编程中synchronized关键字的基础用法讲解

    多线程编程中,最关键.最关心的问题应该就是同步问题,这是一个难点,也是核心. 从jdk最早的版本的synchronized.volatile,到jdk 1.5中提供的java.util.concurrent.locks包中的Lock接口(实现有ReadLock,WriteLock,ReentrantLock),多线程的实现也是一步步走向成熟化.   同步,它是通过什么机制来控制的呢?第一反应就是锁,这个在学习操作系统与数据库的时候,应该都已经接触到了.在Java的多线程程序中,当多个程序竞争同一

  • 详解Java编程中static关键字和final关键字的使用

    Java static关键字以及Java静态变量和静态方法 static 修饰符能够与变量.方法一起使用,表示是"静态"的. 静态变量和静态方法能够通过类名来访问,不需要创建一个类的对象来访问该类的静态成员,所以static修饰的成员又称作类变量和类方法.静态变量与实例变量不同,实例变量总是通过对象来访问,因为它们的值在对象和对象之间有所不同. 请看下面的例子: public class Demo { static int i = 10; int j; Demo() { this.j

  • 深入解析Java编程中final关键字的作用

    final class 当一个类被定义成final class,表示该类的不能被其他类继承,即不能用在extends之后.否则在编译期间就会得到错误. package com.iderzheng.finalkeyword; public final class FinalClass { } // Error: cannot inherit from final class PackageClass extends FinalClass { } Java支持把class定义成final,似乎违背了

  • Java面向对象编程中final关键字的使用方法详解

    在Java中通过final关键字来声明对象具有不变性(immutable),这里的对象包括变量,方法,类,与C++中的const关键字效果类似. immutable指对象在创建之后,状态无法被改变 可以从三个角度考虑使用final关键字: 代码本身:不希望final描述的对象所表现的含义被改变 安全:final对象具有只读属性,是线程安全的 效率:无法修改final对象本身,对其引用的操作更为高效 final 变量 定义final Object a,则a只能被初始化一次,一旦初始化,a的数据无法

  • 深入解析Java编程中final关键字的使用

    在Java中声明属性.方法和类时,可使用关键字final来修饰.final变量即为常量,只能赋值一次:final方法不能被子类重写:final类不能被继承. 1.final成员 声明 final 字段有助于优化器作出更好的优化决定,因为如果编译器知道字段的值不会更改,那么它能安全地在寄存器中高速缓存该值.final 字段还通过让编译器强制该字段为只读来提供额外的安全级别.   1.1关于final成员赋值 1)在java中,普通变量可默认初始化.但是final类型的变量必须显式地初始化.   2

随机推荐