昨天,有位同事抛出了一个问题:
一个class内有一个private属性的struct类型,然后他想做的事情是,在继承该class的子类中复用这个类型,但是由于该类似的private属性,编译是不通过的。
因此就引入了一个问题:如何突破class的private属性限制——试图破坏class的封装性,有点“逆天而行”的感觉。
查了一下,方法确实是有的。
假设有以下类:
m_nPrivate class X { private: int m_nPrivate; public: X() : m_nPrivate(1) {} template<typename T> void Func(const T &t) {} const int GetValue() { return m_nPrivate; } };这种方法的缺点:计算偏移量是个麻烦的事情,涉及到内存对齐、编译器版本等,可移植性低,而且这种方法只能访问成员变量,却不能达到“使用private内置类型”的目的。
在类X的定义前,加一句:
#define private public该方法可以欺骗编译器,让它把“private”当作“public”。
然而它有两个违背标准的行为:
1)#define 保留字是非法的
2)违反了唯一定义规则(ODR,One Definition Rule),然而类的底层内存布局没改变,故可行
首先我们将X类型的指针转换为Y类型的指针,在编译器看来,我们访问的是Y类型的public成员m_nNotPrivate,因此编译通过,然而事实上该指针是X类型的,由于Y跟X的内存布局是完全一样,因此访问Y的m_nNotPrivate成员实际上也就是在访问X的m_nPrivate成员。
类似的方法就是,在Y中增加一个非虚成员函数,该函数用来返回m_nPrivate的地址。
类似以上方法,不过是通过添加友元声明来访问的~
如果X中存在一个成员模版,那么可以这样子:
namespace { struct Y{}; } template<> void X::Func(const Y&) //特化 { m_nPrivate = 2; } void Test() { X x; cout << x.GetValue() << endl; x.Func(Y()); cout << x.GetValue() << endl; }这种方法利用了X具有一个成员模板的事实,通过特化函数模版,来打入敌人内部。代码完全符合标准,标准也确保这种行为会按照编码者的意图行事。boost和loki中大量运用此手法。
以上方法参考:http://blog.csdn.net/chenyu2202863/article/details/5043106