c++ - 使用模板技巧访问私有(private)成员

标签 c++ templates

来自博客文章 Access to private members: Safer nastinessJohannes Schaub - litb :

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

如何get函数可以从 a 调用对象,因为它没有在 class A 内部定义?

编辑:

我不明白为什么 get 必须有 Tag 作为参数而不是 a.*get<A_f>() => 好的,这是由于 ADL 机制

最佳答案

你不是从 a 调用 get !实际上得到的返回是一个指向 A 内部成员的类指针,它的类型是 int A::* 所以你需要一个 A 的实例> 访问该值。

例如,让我玩一下你的代码:

struct A {
    A(int a):a(a) { }
    int b;
private:
    int a;
};
void test() {
    auto p = &A::b;
    std::cout << a.*p << std::endl;
}

我是否从 a 内部调用了 pa 没有 p,这正是你的代码中发生的情况,get 函数返回 &A::a然后你使用 a 来读取它的值!就是这样,没有错,我认为它会在所有编译器中编译。

这里的另一个问题是:为什么 C++ 允许使用 A 的私有(private)成员声明模板。 C++ 标准说:

14.7.2p8 The usual access checking rules do not apply to names used to specify explicit instantiations. [Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible.]

但是如果你尝试实例化甚至是 typedef 指定的模板那么你会得到一个错误。 让我们稍微修改一下您的示例:

struct A {
private:
    int a;
    friend void f();
};

// Explicit instantiation - OK, no access checks
template struct Rob<A_f, &A::a>;

// Try to use the type in some way - get an error.
struct Rob<A_f, &A::a> r;            // error
typedef struct Rob<A_f, &A::a> R;    // error
void g(struct Rob<A_f, &A::a>);      // error

// However, it's Ok inside a friend function.
void f() {
    Rob<A_f, &A::a> r;               // OK
    typedef Rob<A_f, &A::a> R;       // OK
}

关于c++ - 使用模板技巧访问私有(private)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12993219/

相关文章:

c++ - 向套接字发送数据导致异常

c++ - 将数据集转换为任何 STL 容器

c++ - lambda 表达式的可变参数模板

c++ - 模板类层次好友继承

python - C++ 和 cython - 寻求一种避免模板限制的设计模式

c++ - 在 C 中使用具有虚拟成员(即非 POD)的 C++ 结构

c++ - 如何从位图文件创建 .sub (vobsub sutitle sub/idx) 文件

c++ - 如何在 Windows 7 中申请管理员权限?

c++ - 覆盖语法,返回指向固定大小数组的指针的专用模板方法

c++ - 如何专门化用作函数参数的模板类型名?