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,其友元关系的对象及其派生类都可以其友元对象派生类的私有方法。