创意组合——friend class + virtual class member

noiile

noiile@hotmail.com

 

friend class可以让友元类访问到自己类的私有成员。

virtual class member的声明可以让程序访问到真正的对象的成员。

 

class a声明了class c是其友元类,所以class c可以访问到class a的私有成员。

但是friend关系是不可以继承的,也就是说,class d不可以访问到class a的私有成员。有什么办法可以让继承类也能继承这种友元关系呢?

 

办法是有的!

 

如果非要让class d访问class a的成员变量,而又不能在class a中明文声明(通常API编程都是这样,因为不可能知道会有哪个类继承class c。又或者想让程序变的优雅一些,毕竟在一个类中写上太多的友元声明感觉不是很好),那可以在class c中写上getXxx函数,并让其受保护。这样,任何继承自class c的派生类都可以访问class a的私有类了,当然是通过get函数。

代码如下:

#include <iostream>

#include <string>

using namespace std;

 

class a

{

    friend class b;

public:

    a():_a("hello"){}

    ~a(){}

 

    void printA() { cout << _a << endl;}

private:

    string _a;

};

 

class b

{

public:

    void BprintA(a* _a) { cout << _a->_a << endl;}

protected:

    string& getA(a* _a){return _a->_a;}

};

 

class c : public b

{

public:

    void CsetA(a* _a)

    {

        string& a_str = getA(_a);

        a_str = "haha";

    }

};

 

int main()

{

    a my_a;

    my_a.printA();//输出 hello

    b my_b;

    my_b.BprintA(&my_a);//class b可以访问 class a

    c my_c;

    my_c.CsetA(&my_a);//class c也成功访问 class a的私有变量

    my_a.printA();//输出 haha

    return 0;

}

 

class a的私有成员是访问到了,但是我想访问继承自class a的派生类的私有成员呢?

也许你没有明白,也许你认为不实用。那好吧,为了证明我不是讨论些没有用的技术,我结合个实例来说吧。

 

我要实现一个处理事件机制的问题。因为由于event的生命周期由程序来控制,它必须要用new来生成,用delete来释放。而且是由observer处理完之后才释放。为了防止程序员在observer之外意外的delete掉event,我将event的析构函数设为protected。为了防止程序员没有用new来生成对象,我将构造函数也设为protected,提供一个静态方法create()来产生event对象,并返回指针。于是变为下图:

可是问题来了,observer要delete对象event,必须把observer设为event的友元类。

可是真正生成的event对象是它的派生类,真正处理event的也不是observer,而是它的派生类。但是根据event-observer设计模式的原则,实作一个event根本不用关心它的observer对象是哪位。

解决办法很简单,将event的析构函数设为virtual(事实上也应该设为virtual)。问题解决了。如下图:

总结:

这说明了两个问题

1.       派生类可以通过基类的方法操作友元对象的私有成员。

2.       如果友元对象的私有方法设为virtual,其友元关系的对象及其派生类都可以其友元对象派生类的私有方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值