C++篇---访问私有成员的3种情况及友元函数的使用

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;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值