C++友元的简单分析

//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吧。
  毕竟在别人不感知的情况下擅自动别人的底裤是一种不文明的现象。
*/

相关推荐