在C++中,friend是破坏封装性的,friend 的在C++语法体系是一个比较小的知识点,在开发中用的也不是很多。friend 的用法有时很容易忘记,一些陷阱经常跳进去。本文做了一个简短总结。
C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。
这类友元函数最常见,通常是操作符,例如输入输出操作符,示例如下所示:
//OpeClass.h #pragma once class OpeClass { friend OpeClass& operator <<(const OpeClass& xx); public: OpeClass(void); OpeClass(int x,int y); ~OpeClass(void); private: int width; int height; };
//OpeClass.cpp #include "OpeClass.h" OpeClass::OpeClass(void) { width = 50; height = 50; } OpeClass::OpeClass(int x,int y):width(x),height(y) { } OpeClass::~OpeClass(void) { } OpeClass& operator<<(const OpeClass& xx) { cout<<xx.width<<xx.height; return *this; }
类作为友元需要注意的是友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件。但是在原始类的定义中(包含友元类声明的那个类),就不需要包含友元类的头文件.
另外,不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明。
//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 "StdAfx.h" #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.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; int 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"); }
若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
B是A的友元类,C是B的子类,推不出C是A的友元
B是A的友元,C是B的友元,推不出C是A的友元
在用C++实现单例模式时,可以利用友元函数实例化对象。然后把类的构造函数和析构函数都设计成私有函数。
class CMySingleton { public: friend CMySingleton& InstanceMEC(); private: CMySingleton() {}; CMySingleton(const CMySingleton &lxSington) {}; ~CMySingleton(){}; }; CMySingleton& InstanceMEC() { //因为函数InstanceMEC()是类ClxSingletonMEC的友元函数,所以可以访问类所有的成员函数.所以不会有编译错误 static CMySingleton Instance; return Instance; }
原文地址:http://blog.csdn.net/smartfox80/article/details/39547185