繁体   English   中英

为什么此代码允许访问私有变量

[英]Why this code allows accessing private variables

几天前,我遇到了这种方法(作为C ++课程中编程任务的解决方案之一)。

#include <iostream>

struct C {
    C(int i) { m_i = i; }
private:
    int m_i;
};

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

template<typename D>
struct AcessorTag {
    typedef D C::*type;
};

template struct Rob<AcessorTag<int>, &C::m_i>;

int &get_c(C &cls) {
    return cls.*get(AcessorTag<int>());
}

int main()
{
    C c(13);
    std::cout << get_c(c);
    return 0;
}

您能否解释一下为什么编译此代码? 这里发生的几乎所有事情是:1)我们将指针指向成员作为结构模板的参数传递给我们; 2)声明一个朋友函数,该函数仅将该指针返回给成员。

这是标准的C ++吗? (我已经在VS 2015上进行了测试)

get函数是struct Rob<>的朋友,但不是struct C 无论如何, struct C似乎没有朋友,那么为什么它的私有成员可以访问?

谢谢!

除了缺少get函数的前向声明外,此代码还可以正常工作并且符合标准。 由于适用于模板的显式实例化定义的特殊规则,因此可以使用此代码:

17.8.2显式实例化[temp.explicit]

14通常的访问检查规则不适用于用于指定显式实例化的名称。 [注:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是私有类型或对象,通常是无法访问的,并且模板可能是成员模板或成员函数通常是无法访问的。 —尾注]

所以写

template struct Rob<AcessorTag<int>, &C::m_i>;

将绕过常规的访问检查,并提供指向否则无法访问的成员的指针,以get函数体。

这个答案中很好地描述了这种幻想规则的动机。

当然,您的代码无法使用gnu c ++和clang ++进行编译; 标识符get不是C的成员。 即使您尝试实例化Rob ,例如

Rob<AcessorTag<int>, &C::m_i> rob;

您获得

error: 'int C::m_i' is private.

您可以随时询问Microsoft他们的c ++编译器是否符合任何标准。 如果他们完全回答,请告诉我他们的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM