原文地址:
http://www.quanxue.cn/JC_CLanguage/Cpp/Cpp14.html
类的外部,也就是通过实例来访问私有(private)或保护(protected)成员,这是被禁止的。但从实用性来说,的确有时很需要在外部访问,C++增加了一种称之为“友元(friend)”函数的申明,将“特权”赋给一些函数(可以是全局函数,也可以是其它类的成员函数),使之能够访问该类的私有和保护成员。
友元函数必须在类里面申明,而且友元函数一定不是该类的成员函数。因此,这样的“特权”实际上已经不是完全的面向对象设计了,当然,我们也可以不用它。另外,友元函数的申明在派生类无效,除非派生类中再申明一次,当然类型转换为基类时,使用没有任何问题。
一、全局函数作友元
要使用全局函数作友元函数,也就是说全局函数中要使用当前这个类的实例,因此,全局函数的定义必须放在这个类的后面,否则,编译时这个类的实例就成了未定义的数据类型了。
#include <iostream>
#include <string>
using namespace std;
class ca {
string id;
void setId(string s) {
id = s;
}
protected:
string name;
void setName(string s) {
name = s;
}
public:
void print() {
cout << id << " " << name << " " << endl;
}
friend void fun(ca& a); //申明全局函数作友元,允许它访问私有保护成员
};
class derive : public ca { }; //ca类的派生类
void fun(ca& a) { //作友元的函数要定义在那个类的后面
a.id = "987"; //这是ca类的私有成员
a.setName("xyz"); //这是ca类的保护成员
}
int main ( )
{
ca a;
//a.fun(...); //友元函数不是当前类的成员函数,所以这句编译出错
fun(a);
a.print();
derive d;
fun(d); //作参数时,类型转换为ca类
d.print();
return 0;
}
二、其它类的成员函数作友元
别的类的成员函数作友元,也就是说这2个类相互调用,这样无论谁定义在前在后,编译时都有冲突。要解决这个问题,只要将类的申明、定义、实装分开就可以了。请注意例子中的解说。
#include <iostream>
#include <string>
using namespace std;
class ca; //事先申明ca类,确保cb类的定义不出错
class cb { //在ca类之前定义cb类,确保在ca类里申明cb的test()作友元时不出错
public:
void test(ca& a); //由于ca类事先申明,这儿不出错
};
class ca {
string id;
void setId(string s) {
id = s;
}
protected:
string name;
void setName(string s) {
name = s;
}
public:
void print() {
cout << id << " " << name << " " << endl;
}
friend void cb::test(ca& a); //申明cb类的test()函数作友元,允许它访问私有保护成员
};
void cb::test(ca& a) { //作友元的成员函数的实装必须在ca类的后面,否则ca类的成员就未定义了。
a.id = "123"; //这是ca类的私有成员
a.setName("abc"); //这是ca类的保护成员
}
int main ( )
{
ca a;
cb b;
b.test(a);
a.print();
return 0;
}
三、运算符重载中使用友元
下面将上一章最后一个例子稍作修改,操作符重载由类的函数改为全局函数,也就是说,这个运算符不是这个类的,而是正常使用的操作符。注意重载函数的写法与上一章略有不同。不过,改为友元方式其实并没有必要,纯粹是为了讲解“友元”的用法。
#include <iostream>
#include <string>
using namespace std;
class rect {
int x1, y1, x2, y2; //矩形座标
public:
rect() {
x1 = 0, y1 = 0, x2 = 0, y2 = 0;
}
rect(int m1, int n1, int m2, int n2) {
x1 = m1, y1 = n1, x2 = m2, y2 = n2;
}
void print() {
cout << " x1=" << x1;
cout << " y1=" << y1;
cout << " x2=" << x2;
cout << " y2=" << y2;
cout << endl;
}
//rect operator++(); //这是类的运算符的重载
friend rect operator++(rect &ob); //这是全局运算符的重载
};
rect operator++(rect &ob) {
ob.x1++, ob.y1++;
ob.x2++, ob.y2++;
return ob;
}
int main ( )
{
rect r(12, 20, 50, 40);
r.print();
rect obj;
obj = r++;
obj.print();
return 0;
}
并不是所有操作符都可以定义成“友元”,例如“=”就不能用“友元”方式重载。
分享到:
相关推荐
友元函数的声明通常放在类定义的内部,使用`friend`关键字。例如: ```cpp class MyClass { private: int privateData; public: friend void accessPrivateData(MyClass& obj); }; void accessPrivateData...
成员函数和友元函数是两种不同的方法,可以用来实现运算符重载。 **成员函数重载** 成员函数重载是指将运算符作为类的一个成员函数来实现。这样,运算符的操作数之一通常是当前对象(`this`指针)。例如,在上述...
接下来,我们讨论**友元函数**(Friend Function)。友元函数不是类的成员,但可以访问类的私有和保护成员。它可以在类的外部定义,也可以在类内部声明。声明友元函数通常是为了实现特定的功能,而这些功能需要访问...
友元函数是C++语言中一个重要的概念,它突破了面向对象编程中类成员访问的封装性,允许某些外部函数或者类访问当前类的私有成员和保护成员。在实际开发中,合理使用友元函数可以优化代码结构,简化某些操作,但同时...
友元函数的声明需要在类中进行,并且需要使用`friend`关键字。下面是一些关于友元函数的关键点: - **友元函数的参数**:由于友元函数没有`this`指针,因此当需要访问非静态成员时,通常需要传入对象作为参数。 - *...
下面我们将深入探讨C++中的友元函数及其应用。 首先,让我们看一个简单的例子,以Boat和Car类来说明。这两个类都有一个私有属性——重量,这是它们的基本属性,通常不希望外部代码直接访问。然而,在某些情况下,...
### C++中普通函数声明为友元函数的练习之日期间隔 #### 背景介绍 在面向对象编程中,类的设计与实现是至关重要的环节。C++支持通过定义友元函数来增强类的功能,使得非成员函数可以访问类中的私有或保护成员。本篇...
友元函数的实现可以通过多种方式,例如,使用 friend 关键字来定义友元函数,或者使用继承机制来实现类之间的交互。无论使用哪种方式,友元函数都是 C++ 编程语言中的一种重要机制,可以帮助程序员更好地实现类之间...
在C++中,友元函数的声明通常放在类的定义内部,用 `friend` 关键字表示。例如: ```cpp class MyClass { private: int privateData; public: friend void friendFunction(MyClass& obj); }; void friend...
在C++编程中,友元函数是一种特殊类型的函数,它被允许访问类的私有或保护成员,即使这些成员在通常情况下是不可见的。在本题中,我们需要设计一个友元函数来计算两个日期之间的天数差异。下面将详细阐述如何实现这...
在C++编程语言中,重载运算符和友元函数是两个重要的概念,它们扩展了C++的灵活性和表达能力。下面将详细讲解这两个主题及其在实际编程中的应用。 首先,我们来探讨重载运算符。重载运算符是指在同一个作用域内为一...
友元函数和友元类的需要:类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又...
友元函数的好例子 lass X { private: int i; public: X(int ii) { i=ii; } int getX() { return i; } friend int g(X x
### 友元函数与函数重载在C++中的应用 #### 概述 在C++编程语言中,类是封装数据和操作数据的方法的一种手段。然而,在某些情况下,可能需要让一个非成员函数访问类的私有或保护成员。这时就需要使用到友元函数的...
1. 友元函数(Friend Function) 友元函数是在类的外部定义的函数,但被声明为该类的朋友,因此它可以访问该类的私有和受保护的成员。在例子中,`show()`函数被声明为`Student`类的友元函数。`show()`不是`Student`...
这个实例将探讨如何通过成员函数和非成员函数两种方式来重载运算符,以及如何结合友元函数来实现特定的操作。首先,让我们深入理解运算符重载的概念。 **运算符重载原理** 运算符重载并不创建新的运算符,而是为已...
在类定义中声明友元函数时,需在其函数名前加上关键字 friend。此声明可以放在公有部分,也可以放在私有部分。友元函数可以定义在类的内部,也可以定义在类的外部。 友元函数的特点是可以访问类对象的私有成员,但...
"友元函数详解" 友元函数是 C++ 中的一种机制,允许其他类或函数直接访问类的私有变量,从而实现类之间的数据共享。友元函数可以提高效率,表达简单、清晰,但同时也会破坏封装机制,需要谨慎使用。 友元函数的...
运算符重载:友元(friend)函数问题
1. 友元函数(Friend Function) 友元函数是在类的定义外部定义的函数,它可以访问类的私有和受保护成员。声明友元函数的关键字是`friend`。在示例代码中,`show()`函数被声明为`Student`类的友元,允许它访问`...