英文:
How to access private members of a private type in C++?
问题
要访问私有成员而不修改.h文件,您可以使用以下示例中的代码:
class X
{
private:
class A
{...};
std::vector<A> arr;
};
问题:如何访问X::arr?
class X
{
private:
int a;
};
template<typename Tag, typename Tag::type Member>
struct XAccessor
{
friend typename Tag::type get(Tag)
{
return Member;
}
};
struct X_A
{
typedef int X::* type;
friend type get(X_A);
};
template struct XAccessor<X_A, &X::a>;
// ...
auto x = new X;
(*x).*get(X_A()) = 11;
// ...
我在网上找到了这种方法,但是当我将typedef int X::* type
更改为typedef std::vector<X::A> X::* type
时,它会报错,说X::A
不可访问。
英文:
I want to access private members without modifying the .h file.
This is an example of a .h file
class X
{
private:
class A
{...};
vector<A> arr;
}
Q:How can I access X::arr ?
class X
{
private:
int a;
};
template<typename Tag, typename Tag::type Member>
struct XAccessor
{
friend typename Tag::type get(Tag)
{
return Member;
}
};
struct X_A
{
typedef int X::* type;
friend type get(X_A);
};;
template struct XAccessor<X_A, &X::a>;
...
auto x = new X;
x->*get(X_A())=11;
...
I found this approach online, but when I changed typedef int X::* type
to typedef vector<X::A> X::* type
, it gave me an error saying that X::A
is not accessible.
答案1
得分: 8
如果你能窃取数据成员指针,你可以从中提取类型。以下是一个解决方案,对原始的 X
没有进行任何修改。
假设我们有一个无法修改的类 X
,其中包含一个私有数据成员,类型为私有类型 Hidden
。在你的示例中,Hidden = std::vector<A>
。
我们可以创建一个函数,返回数据成员指针 X::*a
,而无需命名类型为 X::Hidden
:
// 以下三个声明为我们提供了对 X::a 的数据成员指针
auto steal();
template <auto Ptr>
struct Thief {
friend auto steal() {
return Ptr;
}
};
// 显式实例化 Thief<&X::a>
template struct Thief<&X::a>;
之所以这样做有效,是因为当显式实例化模板时,成员访问限制被禁用,因此 Thief<&X::a>
不会导致编译失败。这是有意设计的,否则你将无法显式实例化涉及非公有成员的任何模板。
Thief
定义了一个隐藏的友元函数 steal()
,它返回数据成员指针,并充当封装的“越狱”功能。steal()
只是一个自由函数,并不包含 &X::a
或 X::Hidden
在任何模板参数或函数参数中,因此没有限制我们对它的访问。
我们还创建了一个类型特征,以便从该指针中提取数据类型:
// 可以从数据成员指针中提取 Hidden 的特征
template <typename T>
struct member_type;
template <typename C, typename M>
struct member_type<M C::*> {
using type = M;
};
最后,我们能够访问私有类型 X::Hidden
和私有数据成员 X::a
:
// X_Hidden = X::Hidden
using X_Hidden = member_type<decltype(steal())>::type;
// 在运行时窃取私有数据成员
X_Hidden get_a(const X &x) {
X_Hidden X::*a = steal();
return x.*a;
}
英文:
If you can steal the data member pointer, you can extract the type from it. Here is a solution that works with zero modifications to the original X
.
Say we have a class X
which we can't modify, containing a private data member of private type Hidden
. In your example, Hidden = std::vector<A>
.
class X
{
private:
struct Hidden {};
Hidden a;
};
We can create a function that returns the data member pointer X::*a
, without naming the type X::Hidden
:
// the following three declarations give us a data member pointer to X::a
auto steal();
template <auto Ptr>
struct Thief {
friend auto steal() {
return Ptr;
}
};
// explicit instantiation of specialization Thief<&X::a>
template struct Thief<&X::a>;
The reason why this works is that member access restrictions are disabled when explicitly instantiating templates, so Thief<&X::a>
will not fail to compile.
This is intentional design, because otherwise you would be unable to explicitly instantiate any templates involving non-public members.
Thief
defines a hidden friend steal()
, which returns the data member pointer, and acts as a "jailbreak" for encapsulation.
steal()
is just a free function, and doesn't contain &X::a
or X::Hidden
in any template parameters or function parameters, so nothing restricts our access to it.
We also create a type trait so we can extract the data type from this pointer:
// trait which lets us extract Hidden from a data member pointer
template <typename T>
struct member_type;
template <typename C, typename M>
struct member_type<M C::*> {
using type = M;
};
Finally, we are able to access both the private type X::Hidden
, and the private data member X::a
:
// X_Hidden = X::Hidden
using X_Hidden = member_type<decltype(steal())>::type;
// steal private data member at runtime
X_Hidden get_a(const X &x) {
X_Hidden X::*a = steal();
return x.*a;
}
答案2
得分: -5
在C++中,私有成员被故意隐藏,不能直接从类外部访问。封装的概念确保类的内部实现细节不会暴露给外部实体。
英文:
In C++, private members are intentionally hidden and cannot be accessed directly from outside the class. The concept of encapsulation ensures that the internal implementation details of a class are not exposed to external entities.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论