如何在 C++ 中访问私有类型的私有成员?

yaw*_*w x -1 c++ templates boost c++-loki

我想在不修改 .h 文件的情况下访问私有成员。这是 .h 文件的示例

class X
{
private:
   class A
   {...};
   vector<A> arr;
}
Run Code Online (Sandbox Code Playgroud)

问:如何访问 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;
...
Run Code Online (Sandbox Code Playgroud)

我在网上找到了这种方法,但是当我更改typedef int X::* type为时typedef vector<X::A> X::* type,它给了我一个错误,说X::A无法访问。

Jan*_*tke 8

如果您可以窃取数据成员指针,则可以从中提取类型。这是一个对原始版本进行零修改的解决方案X

假设我们有一个X无法修改的类,其中包含 private 类型的私有数据成员Hidden。在你的例子中,Hidden = std::vector<A>.

class X
{
private:
    struct Hidden {};
    Hidden a;
};
Run Code Online (Sandbox Code Playgroud)

我们可以创建一个返回数据成员指针的函数X::*a,而无需命名类型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>;
Run Code Online (Sandbox Code Playgroud)

这样做的原因是显式实例化模板时禁用成员访问限制,因此Thief<&X::a>不会编译失败。这是有意设计的,因为否则您将无法显式实例化任何涉及非公共成员的模板。

Thief定义了一个隐藏的friend steal(),它返回数据成员指针,并充当封装的“越狱”。 steal()只是一个自由函数,不包含&X::a任何X::Hidden模板参数或函数参数,因此没有任何东西限制我们对它的访问。

我们还创建了一个类型特征,以便我们可以从此指针中提取数据类型:

// 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;
};
Run Code Online (Sandbox Code Playgroud)

最后,我们能够访问私有类型X::Hidden和私有数据成员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;
}
Run Code Online (Sandbox Code Playgroud)

请参阅Compiler Explorer 上的现场演示

  • @PepijnKramer 我将给予 OP 怀疑的好处,并假设他们已被遗留代码库和奇怪的需求逼入绝境,并且别无选择。无论如何,问题不是要不要做,而是如何做。当OP问“我如何搬起石头砸自己的脚?”时,我唯一的工作就是告诉他们如何关闭保险并扣动扳机:3 (3认同)