This question already has an answer here:
I can't understand this line - dereferencing an address of private member variable or what?
(1个答案)
4年前关闭。
我偶然发现this question,它的答案使用了一个奇怪的构造:
我通常会遵循
没有
这条线需要分解。我将在更多行中进行:
第一行定义了指向
第二行获取指向
您不能直接在
您可以将成员指针视为另一种类型的“类型化偏移量”:
然后,我们将此成员指针与
所以看起来好像有一个运算符
然后关闭静态方法和
叫它。这种技术可以访问
(1个答案)
4年前关闭。
我偶然发现this question,它的答案使用了一个奇怪的构造:
typedef std::queue<int> Q;
typedef Q::container_type C;
C & get (Q &q)
{
struct hack : private Q {
static C & get (Q &q) {
return q.*&hack::c;
}
};
return hack::get(q);
}
我通常会遵循
q
可以访问由c
函数引用的自己的get
成员的功能。但是,我不知所措,无法清楚地解释它。 .*&
到底发生了什么,为什么允许它? 最佳答案
typedef std::queue<int> Q;
Q
是适应queue
的容器。typedef Q::container_type C;
C
是Q
的基础容器-这是deque<int>
。C & get (Q &q) {
get
接受queue
并返回deque
。实际上,它返回deque
包装的queue
:通过常规方式,这是不可能的。 struct hack : private Q {
hack
是函数的本地类型。它继承自Q
,并且只有一个静态成员函数。从它的名字,您可能会怀疑它是一个hack。你是对的。没有
hack
实例化。 static C & get (Q &q) {
hack::get
与get
本身具有相同的签名。实际上,我们将get
的所有工作委托(delegate)给此方法。 return q.*&hack::c;
这条线需要分解。我将在更多行中进行:
using mem_ptr_t = C Q::*; // aka typedef C Q::*mem_ptr_t;
mem_ptr_t c_mem_ptr = &hack::c;
C& ret = q.*c_mem_ptr;
return ret;
第一行定义了指向
C
中类型为Q
的字段的成员指针的类型。用C++ 11和C++ 03命名此类型的方法都很难看。第二行获取指向
c
中的Q
字段的成员指针。它是通过C++类型系统中的漏洞来完成的。 &hack::c
在逻辑上是C hack::*
类型的-指向C
类型的类中的hack
类型的成员的指针。实际上,这就是为什么我们可以在static
的hack
成员中访问它的原因。但是有问题的c
实际上在Q
中,因此C++中表达式的实际类型是C Q::*
:指向Q
成员变量的指针。您不能直接在
hack
中获取此成员指针-&Q::c
是非法的,但&hack::c
不是非法的。您可以将成员指针视为另一种类型的“类型化偏移量”:
&hack::c
是c
中Q
的“偏移量”,并且知道其类型为C
。现在这不是真的-它是一个不透明的值,告诉编译器如何从c
中获取Q
,但是它有助于以这种方式思考(在简单的情况下也可以以这种方式实现)。然后,我们将此成员指针与
Q&
一起使用,以从c
中获取Q
。获取成员指针受到保护的约束:使用它不是!我们的方法是使用运算符.*
,它是成员取消引用运算符,您可以在右侧传递成员函数指针或成员,在左侧传递类实例。instance .* member_ptr
是一个表达式,可在member_ptr
中找到instance
“指向”的成员。在原始代码中,所有操作都在一行上完成:instance .* &class_name::member_name
所以看起来好像有一个运算符
.*&
。 }
};
然后关闭静态方法和
hack
类,然后: return hack::get(q);
}
叫它。这种技术可以访问
protected
状态:没有它,只能在同一实例的子类中访问protected
成员。使用此方法,我们可以访问任何实例的protected
成员,而不会违反任何标准。10-04 12:35