文章参考:
1. 语法改进
在C++98中,如果想要声明类B是类A的友元类,需要class
关键字,而在C++11中,可以省略关键字class
,还可以使用别名。
EG:
-
C++98中:
class B; class A{ friend class B; // 将B声明为A的友元 private: int num; } class B{ private: A a; public: B(){ a.num = 10; // 因为B是A的友元,所以B可以直接访问A内所有访问属性的成员 } }
-
C++11中:
class B; using B_1 = B; typedef B B_2; class A{ friend B; // 省略关键字class friend B_1; // 使用别名声明友元类 friend B_2; // 使用别名声明友元类 private: int num; }
2. 为类模板声明友元
C++11为我们提供了新的友元功能,即:为类模板声明友元。这样我们就可以根据需要来确定友元类。
注意:如果模板参数是基础数据类型,如int
、double
,那么该模板参数的友元声明将会被忽略。
语法:
template <typename T>
class Test{
friend T;
};
struct Base{
int num;
}
int main(void){
Test<Base> t1;
Test<int> t2;
return 0;
}
- 第9行:
Base
类是Test
的友元。 - 第12行:
int
是基础数据类型,因此友元声明被忽略。
EG:
-
场景:
假设有一个矩形类、一个圆形类,在对其进行一些操作后,我们需要验证矩形的宽度和高度、圆形的半径是否满足要求,并且这些校验要求在另一个类中完成。
-
代码:
#include <iostream> using namespace std; template <typename T> class Rectangle{ private: double h; double w; public: friend T; // 友元声明 Rectangle(double width, double height): w(width), h(height){} }; template <typename T> class Circle{ private: double r; public: friend T; // 友元声明 Circle(double radius): r(radius){} }; class Verify{ public: Verify(double w, double h, Rectangle<Verify>& rectangle){ if( rectangle.w >= w && rectangle.h >= h ){ cout << "yes" << endl; } else{ cout << "no" << endl; } } Verify(double r, Circle<Verify>& circle){ if( circle.r >= r ){ cout << "yes" << endl; } else{ cout << "no" << endl; } } }; int main(void){ Rectangle<Verify> r(10, 20); Circle<Verify> c(10); Verify v1(10, 10, r); Verify v2(20, c); return 0; }
-
输出:
yes no