友元——让函数或者类作为另外一个类的朋友,则可以访问当前类的private或者protected
友元friend机制允许一个类授权其他的函数访问它的非公有成员
友元声明以关键字friend开头,它只能出现在类的声明中,它们不受其在类体中的public、private和protected区的影响
一个普通函数作为类的友元,那么在当前函数中就可以通过对象访问类的私有或者保护成员
注意:这个函数只能在外部定义,在当前类中引用即可
- class A
- {
- public:
- A(int i=0):m_i(i){}
- int GetI()const
- {
- return m_i;
- }
- friend void Add(A& a, A& b);
- protected:
- //friend void Add(A& a, A& b);//将Add函数作为类A的友元,在内部并不能定义
- private:
- //friend void Add(A& a, A& b);//在保护和私有都能正确运行
- int m_i;
- };
-
- //想在Add函数中访问私有数据成员,又不想通过接口(共有函数)
- void Add(A& a, A& b)
- {
- cout << a.m_i << endl;
- cout << b.m_i << endl;
- cout << a.m_i + b.m_i << endl;
- //cout << a.GetI() + b.GetI() << endl;
- }
- void main()
- {
- A a(5);
- A b(8);
- Add(a, b);
- }
函数不止能作为一个类的友元
- class B;//前向引用声明
- class A
- {
- public:
- A(int i=0):m_i(i){}
- friend int Sum(A& a, B& b);//在这之前未定义class B,需进行声明
- private:
- int m_i;
- };
- class B
- {
- public:
- B(int j = 0) :m_j(j) {}
- friend int Sum(A& a, B& b);//一般情况下放在共有里面
- private:
- int m_j;
- };
- int Sum(A& a, B& b)
- {
- return a.m_i + b.m_j;
- }
- void main()
- {
- A a(20);
- B b(20);
- cout << Sum(a, b) << endl;
- }
一个类的成员函数作为另一个类的友元
注意:成员函数建议放在类外定义
- class A;
- class B
- {
- public:
- B(int j = 0) :m_j(j) {}
- void Sub(A& a);
- void Print(A& a);
- private:
- int m_j;
- };
- class A
- {
- public:
- A(int i = 0) :m_i(i) {}
- friend void B::Sub(A& a);//
- friend void B::Print(A& a);
- private:
- int m_i;
- };
- void B::Sub(A& a)
- {
- cout << a.m_i - m_j << endl;
- }
- void B::Print(A& a)
- {
- cout << a.m_i << endl;
- }
-
- void main()
- {
- A a(40);
- B b(20);
- b.Sub(a);
- }
一个类A作为另外一个类B的友元类,则A的所有的成员函数就可以访问B的私有数据成员或者保护
整个类可以是另一个类的友元。友元类的每个成员函数都是另一个类的友元函数,都可以访问另一个类中的所有成员,公有、保护或私有数据成员。
- class B;
- class A
- {
- public:
- A(int a=0):m_a(a){}
- void print(B& b);
- void test(B& b);
- void show(B& b);
- private:
- int m_a;
- };
- class B
- {
- public:
- B(int b=0):m_b(b)
- friend class A;
- private:
- int m_b;
- };
- void A::print(B& b)
- {
- cout <<"print"<< b.m_b << endl;
- }
- void A::test(B& b)
- {
- cout << "test"<
- }
- void A::show(B& b)
- {
- cout << "show"<
- }
- void main()
- {
- B b(30);
- A a(40);
- a.print(b);
- a.show(b);
- a.test(b);
- }
总结:
1、 友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符"."加对象成员名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员。
2、友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果都一样。
3、某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。
二、友元特点:
1、友元是单向的:A是B的友元,并不意味B是A的友元
- class B;
- class A
- {
- public:
- A(int a=0):m_a(a){}
- void print(B& b);
- void test(B& b);
- void show(B& b);
- friend class B;
- private:
- int m_a;
- };
- class B
- {
- public:
- B(int b=0):m_b(b){}
- friend class A;
- void Print(A& a);//
- private:
- int m_b;
- };
- void B::Print(A& a)
- {
- cout << a.m_a << endl;//友元是单向的,需在A中再次声明friend B
- }
- void A::print(B& b)
- {
- cout <<"print"<< b.m_b << endl;
- }
- void A::test(B& b)
- {
- cout << "test"<
- }
- void A::show(B& b)
- {
- cout << "show"<
- }
- void main()
- {
- B b(30);
- A a(40);
- a.print(b);
- a.show(b);
- a.test(b);
- b.Print(a);
- }
2、友元是不能传递的:A是B的友元,B是C的友元,但A不是C的友元
BB是AA的朋友,CC是BB的朋友,如果CC没有作为AA的友元类,则CC和AA没有关系——友元不能传递
- class BB;
- class CC;
- class AA
- {
- public:
- AA(int a=0):m_a(a){}
- friend class BB;
- private:
- int m_a;
- };
- class BB
- {
- public:
-
- friend class CC;
- void Show(AA& a);
- private:
- int m_b;
- };
- class CC
- {
- public:
- void print(BB& b);
- void test(AA& a);
- };
- void BB::Show(AA& a)
- {
- cout << a.m_a << endl;
- }
- void CC::print(BB& b)
- {
- cout << b.m_b << endl;
- }
- void CC::test(AA& a)
- {
- cout << a.m_a << endl;//error CC不是AA的朋友(友元不能传递)
- }
- void main()
- {
- }
3、友元是不能继承的:Base类型继承Object类型,如果Object类型是A的友元,但Base类型不是A友元。
三、友元函数在运算符重载中的应用
1、不同类型对象,但数据成员个数与类型一致,重载+
- class B;
- class A
- {
- public:
- A(int i=0):m_i(i){}
- int operator+(B& b);
- private:
- int m_i;
- };
- class B
- {
- public:
- B(int j=0):m_j(j){}
- friend int A::operator+(B& b);
- private:
- int m_j;
- };
- int A::operator+(B& b)
- {
- return m_i + b.m_j;
- }
- void main()
- {
- A a(10);
- B b(20);
- cout << a + b << endl;//a.+(b) +(a,b)
- }
2、 重载成员函数调用可以省略一个参数
重载友元函数不能省略
- class A
- {
- public:
- A(int i=0):m_i(i){}
- void print()
- {
- cout << m_i << endl;
- }
- A operator+(A& b)//this
- {
- return m_i + b.m_i;
- }
- friend A operator-(A& a, A& b);
- A operator++(int)//a++值返回
- {
- int t = m_i;
- m_i = m_i + 1;
- return t;
- }
- friend A& operator++(A& a);
- private:
- int m_i;
- };
- A operator-(A& a, A& b)
- {
- return a.m_i - b.m_i;
- }
- A& operator++(A& a)
- {
- ++a.m_i;
- return a;
- }
- void main()
- {
- A a(5);
- A b(10);
- (a + b).print();
- (a - b).print();
- (a++).print();
- (++b).print();
- }
3、重载输出运算符(输出对象(即输出对象中的数据成员))
cout——ostream类的对象
cin——istream类的对象
cout<
一般情况下运算符可以解析成下面两种形式:
1、cout.<<(a) ostream类中重载了<<,程序员不能修改
2、<<(cout,a) 可以在程序员自己定义的类中将<<重载成友元
cout<
cout<
(cout<
friend ostream& operator<<(ostream &out,A &a)
- class A
- {
- public:
- A(int i=0):m_i(i){}
- friend ostream& operator<<(ostream& out, A& a);
- private:
- int m_i;
- };
- ostream& operator<<(ostream& out, A& a)
- {
- out << a.m_i;
- return out;
- }
- void main()
- {
- A a(5);
- cout << a;//cout<<(a) <<(cout,a)
- }
练习:
输出值为:0,8,5
- class Magic
- {
- double x;
- public:
- Magic(double d=0.00):x(fabs(d)){}
- Magic operator+(Magic c)
- {
- return Magic(sqrt(x * x + c.x));
- }
- friend ostream& operator<<(ostream& os, Magic c);
-
- };
- ostream& operator<<(ostream& os, Magic c)
- {
- return os << c.x;
- }
- void main()
- {
- Magic ma;
- cout << ma << "," << Magic(-8) << "," << ma + Magic(-3) + Magic(-4);
- }
-
相关阅读:
[libopenh264 @ 0x563c78392040] Incorrect library version loaded
高级运维学习(十三)三表五链
Djiango 模版系统详解(ORM数据模型-使用mysql数据库增删改查)
Spring – 记录传入请求
数字藏品系统开发,基于区块链智能合约技术
Linux命令从入门到实战 ---- 用户管理命令
Go常见错误第15篇:interface使用的常见错误和最佳实践
【算法】选择排序
从 min 到 max 的随机数
Eureka: Netflix开源的服务发现框架
-
原文地址:https://blog.csdn.net/weixin_59179454/article/details/127574320