1. 友元函数
友元函数引入:
-
私有成员对于类外部的所有程序部分而言都是隐藏的,访问它们需要调用一个公共成员函数,但有时也可能会需要创建该规则的一项例外。
-
友元函数是一个不属于类成员的函数,但它可以访问该类的私有成员。换句话说,友元函数被视为好像是该类的一个成员。友元函数可以是常规的独立函数,也可以是其他类的成员。实际上,整个类都可以声明为另一个类的友元。
-
为了使一个函数或类成为另一个类的友元,必须由授予它访问权限的类来声明。类保留了它们的朋友的 “名单”,只有名字出现在列表中的外部函数或类才被授予访问权限。通过将关键字 friend 放置在函数的原型之前,即可将函数声明为友元。
友元函数说明
- 必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分;
- 注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"::“指示属于哪个类,只有成员函数才使用”::"作用域符号;
- 友元函数不能直接访问类的成员,只能访问对象成员,
- 友元函数可以访问对象的私有成员,但普通函数不行;
- 调用友元函数时,在实际参数中需要指出要访问的对象,
- 类与类之间的友元关系不能继承。
- 一个类的成员函数也可以作为另一个类的友元,但必须先定义这个类。
2. 访问私有成员的3种情况
No.1
- 说明: 一个全局函数想访问一个类对象的私有成员
- 解决方法: 在该类中把那个全局函数定义为该类的友元函数
- 举例:
#include<iostream> #include <math.h> using namespace std; class Point { int x, y; public: Point(int x= 0, int y = 0); void disp(); // 友元函数的声明 friend double dist(Point p1, Point p2); }; Point::Point(int x, int y) { this->x = x; this->y = y; } void Point::disp() { cout << '(' << x << ',' << y << ')' << endl;} // 因访问类对象的私有属性,在类中定义友元函数 double dist(Point p1, Point p2) { double x = p1.x - p2.x; double y = p1.y - p2.y; return sqrt(x*x+y*y); } int main() { Point p1(0,0), p2(1,1); double dis = dist(p1,p2); cout << "distance of p1 and p2: " << dis << endl; system("pause"); return 0; }
No.2
- 说明: 一个类中的成员函数想访问另一个类对象的私有成员
- 解决方法: 可以在被访问对象类中定义该函数为友元函数
- 举例:
#include<string> #include<iostream> using namespace std; class Teacher; // 声明类 class Student { string name; int age; int score; public: Student(){}; Student(string name="onname", int age=18); void disp(); // 定义Teacher类的setScore成员函数为该类的友元函数 friend void Teacher::setScore(Student &s, int score); }; Student::Student(string name, int age) { this->name = name; this->age = age; score = 0; } void Student::disp() { cout << "I am a student!" << endl; cout << name << " " << age << " " << score << endl; } class Teacher { string name; int age; public: Teacher(){}; Teacher(string name="onname", int age=30); void disp(); // 为了改变学对象的成绩,使用引用类型 void setScore(Student &s, int score); }; Teacher::Teacher(string name, int age) { this->name = name; this->age = age; } void Teacher::disp() { cout << "I am a teacher!" << endl; cout << name << " " << age << endl; } // 因要访问别的类对象的私有成员,需定义友元函数 void Teacher::setScore(Student &s, int score) { s.score = score; } int main() { Teacher t = Teacher("Jack"); t.disp(); Student s = Student("Mary", 19); s.disp(); // 老师修改学生成绩 t.setScore(s,90); t.disp(); return 0; }
No.3
- 说明: 一个类中的一个对象想访问同类中的另一个对象的私有成员,可直接访问
- 举例
#include<iostream> using namespace std; class Complex { private: int real, imag; public: Complex(int r = 0, int i = 0); void disp(); void input(); Complex operator+(Complex c); }; Complex::Complex(int r, int i) { this->real = r; this->imag = i; } void Complex::disp() { cout << real << " " << imag << endl; } Complex Complex::operator+(Complex c) { // 直接用传入对象的私有属性,将它们实部和虚部分别相加后再利用构造函数创建新对象返回 return Complex(real+c.real,imag + c.imag); } int main() { Complex c1(2,3), c2(2,-3), c3; c3.disp() c3 = c1 + c2; c3.disp(); return 0; }