友元内容总结

本文详细介绍了C++中如何通过友元机制突破类对象的常规访问权限限制,包括友元函数、友元类的使用示例,以及友元在不同场景下的应用,如类间同步和权限共享。
摘要由CSDN通过智能技术生成

概述:

        C++控制对类对象私有部分的访问。公有类方法提供唯一的访问途径,但是这种限制过于严格,以至于不适合特定的编程问题。

        此种情况下,C++提供了另一种形式的访问权限:友元

友元有三种:友元函数、友元类、友元成员函数。

一、友元

1.1创建友元

       非成员函数不能直接访问类的私有数据,至少非常规成员函数不能访问。然而,有一类特殊的非成员函数可以访问类的私有成员,它们被称为友元函数

        (1)将原型放在类声明中,并在原型声明前加上关键字friend:

friend Time operator*(double m,const Time &t);

注意:

        operator*()函数是在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用。

        operator*()函数不是成员函数,但它与成员函数的访问权限相同。

        (2)编写函数定义

        由于它不是成员函数,所以不要使用Time::限定符。另外,不要再定义中使用关键字friend,代码如下

Time operator*(double m,const Time &t)
{
    Time result;
    long toalminutes = t.hours * m * 60 +t.minutes *m;
    result.hours = totalminutes/60;
    result.minutes = totalminutes%6;
    return result;
}

调用方法:

A = operator*(2.75,B);

总之,类的友元函数是非成员函数,其访问权限与成员函数相同。

二、友元函数

2.1友元函数示例

以下为Person类的例子:

#include <iostream>
using namespace std;
class Person
{
public:
Person() {}
Person(int id, string name, int age) :
id(id), name(name), age(age) {}
~Person() {}
/*
当前声明了一个 friend 修饰的函数,要求的参数是
Person 类型的引用
@param p Person 对应的引用
*/
friend void show(const Person & p);
private:
int id;
string name;
int age;
};

        示例当中的内容构建了一个完整结构的Person类,其中show使用了1.1当中的方式,用friend来修饰show函数。

        show 函数是 Person 类的友元函数,可以直接操作使用Person 类内的private 或者 protected 修饰内容。

void show(const Person & p)
{
    cout << "ID : " << p.id
    << ", Name : " << p.name
    << ", Age : " << p.age << endl;
}

int main(int argc, char const *argv[])
{
    Person * p = new Person(1, "苏岩", 16);
    show(*p);
    delete p;
    return 0;
}
在类外实现类内的友元函数
        1. 不需要再次使用 friend 关键字标记,如果有 friend 报错!
        2. 当前函数不需要提供作用域限制,没有所有类声明 正常情况下, private 修饰的内容,类外无法直接使用。友元可以打破权限限制。
        在 Person 类内使用 friend 关键字声明了当前show 函数。编译器认为 show 函数是当前 Person 类的友元函数,可以直接操作存在权限限制的内容。

2.3友元函数同时是两个类的友元

        在1.2的代码基础上,添加第二个类:Student,在这个类当中
class Student
{
public:
Student() {}
Student(int id, string name, int age) :
id(id), name(name), age(age) {}
~Student() {}
/*
show 函数在 Student 类内声明,同时使用 friend 修
饰,告知编译器
当前 show 函数是 Student 的友元函数
*/
friend void show(const Person &p, const Student &s);
private:
int id;
string name;
int age;
};

然后我们修改show函数如下:

void show(const Person &p, const Student &s)
{
    cout << "Person ID : " << p.id << ", Name : " 
    << p.name << ", Age : " << p.age << endl;
    cout << "Student ID : " << s.id << ", Name : " 
    << s.name << ", Age : " << s.age << endl;
}

当前show函数有两个声明,但是声明格式一致,分别在Person和Student类内。同时都采用friend关键字修饰,表示当前show函数是Person和Student的友元函数,可以同时操作Person和Student的权限限制【protected】和【private】内容

int main(int argc, char const *argv[])
{
    Person * p = new Person(1, "张三", 10);
    Student * s = new Student(2, "李四", 5);

    show(*p, *s);

    delete s;
    delete p;
    return 0;
}

        主函数如上,代码在执行之后的结果如下

        可以看到,当前执行结果中展示了两个类当中的内容。

三、友元类

3.1友元类示例

        我们在使用类定义一个事务的时候,当子类需要使用父类的权限限制成员的时候,就用到了友元类,友元类与友元函数相似,在声明一个类的时候,需要在其前面加上关键字“friend”。

        代码如下:

#include <iostream>

using namespace std;
/*
前置声明
*/
class Student;

class Person
{
public:
    Person() {}
    Person(int id, string name, int age) : id(id), name(name), age(age) {}
    ~Person() {}

    friend class Student;

private:
    int id;
    string name;
    int age;

    // void test() { cout << "Person private function !" << endl; }
};

class Student
{
public:
    Student() {}
    Student(int id, string name, int age) : id(id), name(name), age(age) {}
    ~Student() {}

    void show(const Person &p);

private:
    int id;
    string name;
    int age;
};

void Student::show(const Person &p)
{
    // p.test();
    cout << "Person ID : " << p.id
         << ", Name : " << p.name
         << ", Age : " << p.age << endl;
}

        在 Person 类内声明 Student 类是当前 Person 的友元类,这样便可以在Student 类内可以直接访问 Person 的权限限制成员。主函数与运行结果与1.3当中相同。

友元声明可以位于公有、私有、或保护部分,其所在的位置无关紧要

3.2其他友元关系

        假设由于技术进步,出现了交互式遥控器。如,交互式遥控器可以让用户回答电视当中的问题,若回答错误,电视会在控制器上产生嗡嗡声。此时Tv类和Remote类,两者可以相互之间影响对方,因此可以通过让彼此称为对方的友元来实现。

        注意:对于使用Remote对象的Tv方法,其原型可在Remote类声明之前声明,但必须在Remote类声明之后定义,以便编译器有足够的信息来编译该方法

代码如下:

class Tv
{
	friend class Remote;
Public:
	void buzz(Remote& r);
...
};
class Remote
{
	friend class Tv;
public:
	void Bool volup(Tv& t)
	{
		t.volup();
	}
...
};
inline void Tv::buzz(Remote& r)
{
	...
}

        由于Remote的声明位于Tv声明的后面,因此可以在类声明定义当中定义Remote::volup(),但Tv::buzz()方法必须在Tv声明的外部定义,使其位于Remote声明的后面。

3.3共同的友元

        当函数需要访问两个类的私有数据。从逻辑上看,这样的函数应是每个类的成员函数,但是这是不可能的。

        它可以是一个类的成员,同时是一个类的友元,但是有时将函数作为两个类的友元更合适。

例如:假定有一个Probe类和一个Analyzer类,前者表示某种可能编程的测量设备,后者表示某种可编程的分析设备。这两个类都有内部时钟,且希望他们能够同步,则应该包含下设代码:

class Analyzer;
class Probe
{
	friend void sync(Analyzer& a, const Probe& p);
	friend void sync(Probe & p, const Analyzer& a);
};
class Analyzer
{
	friend void sync(Analyzer& a, const Probe& p);
	friend void sync(Probe& a, const Analyzer& p);

};
inline void sync(Analyzer& a, const Probe& p)
{
	...
}
inline void sync(Probe & a, const Analyzer& p)
{
	...
}

 
  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值