当前位置:   article > 正文

C++的模板(七):左值强制类型转换

C++的模板(七):左值强制类型转换

C++中有个特殊指针类型,就是指向数据成员的指针。这个数据成员的指针是可以提取出来的。如:

class Whatever {
public:
	int x;
	int z;
};

int  Whatever::*mp;
mp = &Whatever::x;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如果数据的访问权限是private,则这样不可以。但可以通过模板的办法挑出来:

class Whatever {
	int x;
	int z;
};

template <class M, typename T, T M::*mp>
class Savein{
public:
        static void init() { x=mp; }
		static T M::*x;
};

template class Savein<Whatever , int, &Whatever ::x>;
template<> int Whatever::* Savein<Whatever, int, &Whatever::x>::x;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里必须通过template语法显式声明Savein<Whatever, int, &Whatever::x>这个类。显式声明可以避免访问权限问题。如果没有用这个语法显式实例化这个类,直接用Savein<Whatever , int, &Whatever ::x>仍会碰到访问权限的问题。这样做是妥当的,因为数据成员默认都是private的,如果模板不接受指向private的数据成员的指针,这个语言也就没有这种功能了。

这一步过关之后,可以通过Whatever类的对象或指针和拣出来这个x来访问类的私有数据了,这时已经是运行期问题了。运行期不受访问权限的影响。这也是提取指向数据成员的指针的目的。

Whatever w;
Savein<Whatever, int, &Whatever::x>::init();
w.*Savein<Whatever, int, &Whatever::x>::x =3;
  • 1
  • 2
  • 3

当然这还是累。能不能把Savein的类变量挪到外面来呢?

static unsigned int offset;
template <class M, typename T, T M::*mp>
class Saveout{
public:
        static void init() { reinterpret_cast<T M::*&>(offset)=mp; }
};
template class Saveout<Whatever , int, &Whatever ::x>;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

offset对应原来的类变量x。放到外面后offset不能带模板参数了,所以就让它成为整数值了。指向数据成员的指针概念上虽然复杂,实际内容不过是个记录偏移量的小整数。当然还是需要从mp赋值,但不能从mp转换。指向数据成员的指针,除了转换指向其它数据成员的指针,不能转换成别的类型。所以只能从左边想办法。转城右边类型的引用。这是C++特有的左值强制类型转换。

使用时这个offset再重新转换成数据成员的指针:

Whatever w;
Saveout<Whatever, int, &Whatever::x>::init();
w.*(int Whatever::*&)offset =3;
  • 1
  • 2
  • 3

最后,因为offset 已经是整数类型了,可以对它进行调整,从而运行期访问其他数据成员。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/640005
推荐阅读
相关标签
  

闽ICP备14008679号