//C++友元,包括友元函数和友元类 //C++友元函数 //C++友元类 /* 当某个类A,声明另外一个类B为其友元类的时候,那么在B中可以访问A的private内容 */ #include <iostream> using namespace std; class A { private: friend class B; friend class C; friend void friend_func(A & a); friend void friend_func_pointer(A *a); int i; public: A(int ii):i(ii) { cout<<"constructor A"<<endl; } ~A() { cout<<"deconstructor A"<<endl; } void func() { cout<<"A.i == "<<this->i<<endl; } void set(int ii) { this->i = ii; cout<<"set A.i = "<<this->i<<endl; } }; class B { public: B() { cout<<"constructor B"<<endl; } ~B() { cout<<"deconstructor B"<<endl; } void func(A& a) { cout<<"friend of A is B, something is done in B, A.i = "<<a.i<<endl; return; } }; //在这里我们准备搞一些邪恶的事情,假如C类即使A的派生类,又是A的friend class会怎么样呢? //let‘s have a try //我们知道即使C是A的派生类,在C里面也不能访问其基类的private成员, //那么如果一个类既是它的派生类,又是它的friend class的话,会发生什么有意思的事情呢? class C : public A { private: int j; public: C(int ii, int jj):A(ii), j(jj) { cout<<"constructor C"<<endl; } ~C() { cout<<"deconstructor C"<<endl; } void func(A& a) { cout<<"do something with out telling A. A.i"<<a.i<<endl; } }; //我们定义一个友元函数 void friend_func(A& a) { cout<<"I am a friend func of A, A.i = "<<a.i<<endl; return; } void friend_func_pointer(A *a) { cout<<"I am a friend func of A, which receives of pointer of A, A.i = "<<a->i<<endl; } int main(int argc, char** argv) { B b; A a(1); cout<<"sizeof(B) = "<<sizeof(B)<<endl;//这里输出的B的大小是1个字节,是不是很奇怪?鬼知道C++想干什么 cout<<"sizeof(A) = "<<sizeof(A)<<endl;//这里输出仍然是4个字节,即一个int的大小,说明在A里面申明一个友元并不会导致A的体积变大 cout<<"sizoef(C) = "<<sizeof(C)<<endl; b.func(a); C c(1,2); c.func(a); //c.func();//这里将发生name hiding,我们之前讲过的,会导致编译失败 friend_func(a);//我们在A里面申明friend_func是A的友元函数,那么这个函数就可以访问A中的private成员 //让我们干点刺激的东西吧,当友元遇到up_cast会怎样? 让我们试一试 = =! friend_func(c);//完全没有问题,我们访问到了C里面的东西。实际上从概念上说,我们还是访问对的是A里面的东西 //如果遇到指针的up_cast会发生什么呢?试一试便知道 + + friend_func_pointer(&a); friend_func_pointer((A*)&c);//也完全没有问题 return 0; } /* 关于友元有一些需要注意的概念 (1) 友元关系不能被继承。 B是A的友元class,C是A的子类,但是B不是C的友元。 这一点也很好理解。从封装性的角度考虑,友元class B可以访问A的private内容,但是不应该看到 其子类的private东西。连A都看不到,更别说它的友元class B了。 (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。 这个更好理解了,A说:B,你是我的友元,我的所有东西都可以给你看, 但是B说:好啊,你一厢情愿,我也没有办法。但是我的东西还是不能给你看。 (3) 友元关系不具有传递性。 这一点也比较好理解,假如B是A的friend class, A又是D的友元。 那么B可以看到A的private,A有可以看见D的private,但是B不应该直接看到D的private。 简单的例子就是,我朋友的朋友不一定认识我嘛。 */ //友元函数,是指定义在类的外部,但是可以直接访问类的private成员的函数 //我们还是来上面代码里面的例子吧 /* 总结: 1.一个字,乱 2.个人认为friend class和friend function破坏了oop语言的封装特性。 3.从上面的例子里面可以看到,当friend function遇到了up_cast的时候,friend function破坏了 派生类的内容。 4.any way,我觉得还是不到万不得已的情况下,不要用friend class和friend function吧。 毕竟在别人不感知的情况下擅自动别人的底裤是一种不文明的现象。 */