你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

c++中的友元

[复制链接]
gaosmile 发布时间:2020-8-11 11:28
一、友元的概念:
1、什么是友元?
  • 友元是c++中的一种关系
  • 友元关系发生在函数与类之间或者类与类之间
  • 友元关系是单项的,不能传递

    ' f- a) _! a# Z
微信图片_20200811112716.png
2、友元的用法:
  • 在类中以friend关键字声明友元
  • 类的友元可以是其它类或者具体函数
  • 友元不是类的一部分
  • 友元不受类中访问级别的限制
  • 友元可以直接访问具体类的所有成员
    2 N' }1 _$ P1 P* W+ f
3、友元的语法:
在类中使用friend 关键字对函数或者类进行声明:
class Test8 j- A. b& N, z0 L+ t, u* H
{2 ]! J  K. V7 `, h* T
     double x;( i5 `* L" ~2 h9 d; \' Y3 T
     double y;
0 B% p8 G& W& q+ r9 g9 n! c7 S2 ^. C
/ T+ g8 M5 K' w3 z: B     friend void func(Test& t);
6 ]8 e6 ]/ V" U! d) r( ?' T" k' a5 H: G$ L7 j
};
1 S7 X( F, h" }2 ^! m- v: S) I
8 C+ s: S' j6 p: N' k& P7 nvoid func(Test& t)) Q+ o. z0 m' i) T
{
( M; t) }$ ^* O7 m' }! X' }# c+ U$ j$ W. w
2 {' ?  t$ B' [/ V: u
}

6 k) e8 F6 h! [! E! z' m: t
注意:func() 全局函数是 Test 类的友元,func() 可以访问Test 类的所有成员,但是 func() 不是 Test 的成员函数。
示例代码:
#include <stdio.h>
# `0 i5 P$ W* t. F#include <math.h>
+ f' N" x- {+ ^; G6 d% w, l
( Q: ^; U( H- m3 A: bclass Test
+ x, K, e) w/ \' J1 k4 B- y3 t{
  b, N9 ?, r" T2 L- w" R  l+ n+ o    double x;) \7 M( o9 m( E. l4 G. ^" i
    double y;
4 w. s' W7 J# e$ @% r  jpublic:
+ j, i+ ?1 P: m3 ]$ v  a# H    Test(double x,double y)
$ A& O! J' ?* A0 G: ?% ]0 c    {8 L6 _% E  K% U2 \$ q$ w
       this->x=x;
/ h" B! L" i$ {7 v) G9 l       this->y=y;
& ]$ z# W8 O0 S7 ^! `    }
! R" P! R, K/ R3 D    double getX()
& r; F; `- r, w. M7 K; j/ V: H    {
; O. `; I6 b, U: i/ Y       return x;. A) J  j6 E- o4 y
    }! S# j2 Z* v# Y4 b% e0 U/ [
    double getY()
" r& w0 u5 ~# M# |    {
, n8 Y5 _% O3 q2 u2 h+ W; ~- J& c* c5 S
       return y;8 s) y8 \5 n" {, X+ h
     }
' y- b4 E  S! O' j  E- |    friend double func(Test& t1,Test& t2);3 I% H! ]% i+ Q' G

9 t/ M2 j0 Y; Y- Z& Y1 X) q};- o% {8 F' V1 S2 O- u2 Z
( @) ]! E5 R  w$ E' W) M
double func(Test& t1,Test& t2)
+ u$ q1 |0 z. A* G{
* L. s9 m2 e0 p       double ret =0;
9 W# T: F1 l6 J  E* N4 j% c       ret = (t2.y-t1.y)*(t2.y-t1.y)+(t2.x-t1.x)*(t2.x-t1.x);& U1 b) p. L7 q& i9 q$ `5 \
" `: t! t, L$ u3 I# A; y
        ret = sqrt(ret);9 ?! _9 y( t* S$ V' w
( `0 F! z* X8 ?' Z
     return ret;
  {  [9 \8 u3 p; Q% B, Y; l* T. U/ e+ g3 Z( F" e
}
& b4 c: j% j% |1 Nint main()
7 }3 o0 W1 @3 t6 a  g* n" T, r: x{* B! ^, t9 g# m1 M
    Test t1(1,2);, R# k/ N" N. ], t; C% g7 ?
    Test t2(10,20);) F# r9 M. S* K) Y; G$ R

2 H, s1 g4 ?7 ?- ~2 f    printf("t1(%f,%f)\n",t1.getX(),t1.getY());
6 Z* N- S% R3 T    printf("t2(%f,%f)\n",t2.getX(),t2.getY());" ?' t  R: F; I6 i4 X$ V7 Z3 t! V
    printf("(t1,t2)=%f\n",func(t1,t2));
: u  z# n. [. m6 T% C! |
% i& k( z; t% M$ G" }) Y9 W2 o    $ R3 ~8 {* C( w- u2 g
    return 0;# M9 C- h. F, |
}! ^6 D4 P+ L. T0 L! e

6 R! z0 S, i# a, U( O: m9 z3 P
输出结果:
root@txp-virtual-machine:/home/txp/add# g++ test.cpp
8 b4 M+ R4 w( ?/ y; G& c: aroot@txp-virtual-machine:/home/txp/add# ./a.out
1 Y+ q8 |5 ~% _7 e$ zt1(1.000000,2.000000)+ Y$ }, Y8 {7 A9 y, l
t2(10.000000,20.000000)
4 Y; V6 v# d4 b2 |3 b6 {(t1,t2)=20.124612
$ K4 `7 O5 X0 P3 c
4 H' e8 {, H/ i8 {9 \2 n6 N
4、友元的尴尬:
  • 友元是为了兼顾c语言的高效而诞生的
  • 友元直接破坏了面向对象的封装性
  • 友元在实际开发产品中的高效是得不偿失的
  • 友元在软件工程中已经慢慢被遗弃了

    " p5 V) E8 ^2 }5 ^+ P& ?
5、注意事项:
  • 友元关系不具备传递性
  • 类的友元可以是其它类的成员函数
  • 类的友元可以是某个完整的类
  • 所有的成员函数都是友元

    $ R$ S& r5 A. L" j
微信图片_20200811112721.png
代码测试:
#include <stdio.h>
( n2 J" M: p+ `2 C2 G5 J$ I4 G! W2 R& y# J7 E& ~
class ClassC- L' _: ^3 t% p; b' X0 k$ \
{$ l9 q4 N! Z. J9 F0 l9 F
    const char* n;
' R* C! r5 u; C+ l& p9 |5 k- opublic:
* v2 U+ f1 e# |" E$ d0 x$ O    ClassC(const char* n)7 S; L! R1 l3 e2 {; ]" p
    {% ?0 D- Z4 g2 Y7 O* |; P
        this->n = n;& H( t+ T; o5 K6 U4 |8 u2 N
    }7 c( I, [$ E9 m, Y& u
   
; k4 s* Z7 {; S- p* r  H    friend class ClassB;
+ U7 X/ \6 A7 v5 r, q};3 A% d' D3 M9 V( r) C0 r
( j$ m6 R% e7 ?  e
class ClassB( p+ P& g7 _# r& x: v7 E. q8 N! d
{; m' M4 O* }# d, ]
    const char* n;! E' l& @4 G( P: i. S" D
public:6 v1 [+ ~* f; t) Y8 `
    ClassB(const char* n)
) ?$ ~1 U7 u. d+ a3 u* h$ ~    {$ U& f8 y4 Z8 d$ ?1 p* X
        this->n = n;3 p, }$ F: x; X2 {
    }
; x; D5 t% \0 N' C% C! d    ) p0 _/ {( h1 s9 Q# N; \: y! h
    void getClassCName(ClassC& c)
( o$ A2 k" i, G    {
2 m2 W4 @! m# W2 D: ^  o% m3 A+ m        printf("c.n = %s\n", c.n);
2 ~/ u7 N- I2 Y0 s    }7 e) q- O2 Y' o0 G
    " f% G. w0 K2 Q" s4 n; }
    friend class ClassA;
2 R( R! B  [  k# c: v7 O0 G7 @};& u) A+ Z% }' O* I& ?

1 D4 q1 o; C  I+ G8 ^# ~3 |3 c" x& ]class ClassA
4 L1 }2 A7 Q' Z# W$ ?- y{
$ k$ `0 J! q/ [: w  r5 u2 ^( ~  i    const char* n;, p. P4 ]4 K0 e% M! x8 m
public:
$ q4 K* I+ r. o8 V9 S3 h    ClassA(const char* n)! w4 G8 ^  d! y: F& d% B
    {
" p- Z: b1 p+ ~- {        this->n = n;/ Z* B7 @0 V( h
    }) ]* s; [, o7 X* C
   
$ P0 z$ \0 h9 h0 s# f    void getClassBName(ClassB& b)
+ H6 Y% C+ Q$ i3 Y3 X    {) x) m' b2 E" u, A+ c0 u# K3 }  `3 h
        printf("b.n = %s\n", b.n);
, H9 T0 k0 K# `    }& e7 Z/ K/ ^) O( G
    /*
1 o0 b  a7 ^1 `) o+ P8 ~    void getClassCName(ClassC& c)
1 G% k. Y$ Z/ |8 z7 X    {; u0 h  `2 j$ |: C) v( b0 e6 d: |
        printf("c.n = %s\n", c.n);6 [5 m, `$ M9 m& Y9 w
    }
4 c$ O' U9 m3 K6 i  ?    */( J. F1 L  M; n9 @& `( g5 \
};
! g$ g/ X5 [, Z  I6 Y
2 i) V( k2 h- |( Y- s" `6 eint main()
8 n6 N2 |* \6 S* g7 ?{
; W4 O- N, f" L$ Q! K* X    ClassA A("A");1 _* U: n/ P2 r& P$ I8 o
    ClassB B("B");  q  E1 k+ y; U; l. Q+ t
    ClassC C("C");
) O& M$ J! s2 d1 m  Y    7 e; \' T+ H: s7 q0 G8 B4 k% J: |
    A.getClassBName(B);' x; O1 q( U2 z, ?* e
    B.getClassCName(C);$ F& @( H) f9 P7 Z3 v
   
7 Z/ c  {9 z0 ^- \& S    return 0;
' o3 E2 e7 q' g. j3 S3 V* U. Y}
& Z; I6 R8 V! `
: Z7 R3 m, U8 g$ F( S# v
输出结果:
root@txp-virtual-machine:/home/txp/add# ./a.out
: _+ }2 G1 V8 u) i  {; Hb.n = B: y- {& w- j! ]
c.n = C
/ g7 k6 T" T8 @3 {. g3 T7 ]9 R

* f! @+ y# M1 p  G0 p1 p
如果把上面屏蔽的那部分代码打开,编译就会报错(因为友元没有传递性哦):
root@txp-virtual-machine:/home/txp/add# g++ test.cpp
% [- r  V- k. {9 C& ztest.cpp: In member function ‘void ClassA::getClassCName(ClassC&)’:( b! i+ u/ l5 Z; M9 _) W7 T
test.cpp:5:17: error: ‘const char* ClassC::n’ is private
! L. D  D3 n; c. u4 p     const char* n;
. M1 J  [; `) F0 f                 ^7 p+ [7 i1 i' B1 p3 O( h! K
test.cpp:48:32: error: within this context4 A3 S* D0 Z$ P! t0 [$ A* q& }
         printf("c.n = %s\n", c.n);, P9 j2 d$ o! d  l9 o) a
                                ^
0 R/ B) p7 g' ~9 C
2 g1 y& K- x' Z2 t2 b, \1 |2 F
6、小结:
  • 友元是为了兼顾c语言的高效而诞生的
  • 友元直接破坏了面向对象的封装性
  • 友元关系不具备传递性
  • 类的友元可以是其它类的成员函数
  • 类的友元可以是某个完成的类
    1 Z" [' R% w; c" u
' Q: _8 S- B. E- ?4 E
二、总结:
5 Y; {5 h' L# |  _/ r
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。
2 t9 ~+ m; c; |7 w6 ~& n4 Z9 h
赞 收藏 评论0 发布时间:2020-8-11 11:28

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版