friend关键字扩展

发布时间 2023-12-08 17:33:24作者: Beasts777

文章参考:

爱编程的大丙 (subingwen.cn)

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为我们提供了新的友元功能,即:为类模板声明友元。这样我们就可以根据需要来确定友元类。

注意:如果模板参数是基础数据类型,如intdouble,那么该模板参数的友元声明将会被忽略。

语法:

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