c++ friend关键字
|
1.概述 |
目的: C++通过友元机制允许类的非公有成员被其它类或者非成员函数访问,友元按类型分:普通非类成员函数友元、它类成员函数友元、类友元。 友元包括声明与定义。友元声明默认为了extern,就是说友元类或友元函数作用域已扩展至包含该类定义的作用域,即便在类的内部定义友元函数也没有关系。 |
|
2.普通非成员函数友元
|
语法与普通函数无异,友元函数不属于任何类,其实现可以在类外定义,但必在类内声明,声明需加friend关键字。 #include "cmath" #include "iostream" using namespace std; class Point{ public: Point(double xx,double yy){ x=xx; y=yy;} void GetXY(); friend double Distance(Point &a,Point &b); protected: private: double x,y; }; void Point::GetXY(){ cout<<"("<<x<<","<<y<<")"<<endl;} double Distance(Point &a,Point &b){ double length; length=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //引用类的私有成员 return length; } int main(void){ Point p1(3.0,4.0),p2(6.0,8.0); p1.GetXY(); //成员函数的调用方法,通过使用对象来调用 p2.GetXY(); double d = Distance(p1,p2);//友元函数按普通方式调用,不能按对象方式调用 cout<<d<<endl; system("pause"); return 0; } 说明:上述程序Point类中声明了一个友元函数Distance(),friend关键字标识它非成员函数而是友元函数。它的定义与普通函数定义一致,不能添加类名。它可以引用类中私有成员,函数体中的a.x,b.x,a.y,b.y都是类的私有成员,它们是通过对象引用。 下面对上述代码进行输入、输出流符号重载: #include <cmath> #include <iostream> using namespace std; class Point{ public: Point(double xx,double yy){ x=xx; y=yy;} void GetXY(); friend double Distance(Point &a,Point &b); friend ostream &operator <<(ostream &a,Point &b); protected: private: double x,y; }; ostream &operator <<(ostream &out,Point &b) { out<<"("<<b.x<<","<<b.y<<")"<<endl; return out; } void Point::GetXY(){ //cout<<"("<<this->x<<","<<this->y<<")"<<endl; //cout<<"("<<x<<","<<y<<")"<<endl; cout<<*this; } double Distance(Point &a,Point &b){ double length = sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); return length; } int main(void){ Point p1(3.0,4.0),p2(6.0,8.0); p1.GetXY(); p2.GetXY(); double d = Distance(p1,p2); cout<<d<<endl; system("pause"); return 0; } |
|
3.类友元 |
类作为友元需要注意:友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数访问原始类的私有变量,那么需要在友元类定义文件中包含原始类定义的头文件。但是在原始类的定义中(包含友元类声明的类),不需要包含友元类的头文件。 另外,不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明。 //A.h #pragma once #include <iostream> using namespace std; class A { friend class B; //此处不声明编译报错 public: ~A(void); A(); private: int m_nItem; }; //A.cpp #include "A.h" A::A(){ m_nItem =3; } A::~A(void){}
//B.h #pragma once class B { public: B(void); ~B(void); int func(); }; //B.cpp #include "B.h" #include "A.h" //must include A.h #include <iostream> B::B(void){} B::~B(void){} int B::func() { cout<<"This is in B"<<endl; A a; return a.m_nItem; //访问了A类的成员 } |
|
4.它类成员函数友元 |
声明此种友元要用类限定符,因此必须先定义包含友元函数的类,但是在定义友元函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱(如果是友元类,则没有限制), 如下面所示: //A.h #pragma once #include "B.h" class A{ friend int B::func(A xx); public: A(void):mx(20),my(30){} ~A(void){} private: int mx,my; };
//B.h #pragma once class A; class B{ public: B(void); ~B(void); int func(A xx); }; //B.cpp #include "B.h" #include "A.h" B::B(void){} B::~B(void){} int B::func(A xx){return xx.mx * xx.my;}
//main.cpp #include "A.h" #include "B.h" #include <iostream> using namespace std; void main(){ A a; B b; cout<<b.func(a)<<endl; system("pause"); } |
|
5.其它 |
1. 友元只具单向性:若类B是类A友元,类A不一定是类B友元,要看类中是否有相应声明。 2. 友元不能被继承:B是A的友元类,C是B的子类,推不出C是A的友元。 3. 友元不具传递性:B是A的友元,C是B的友元,推不出C是A的友元。 |

浙公网安备 33010602011771号