是的,我完全清楚我所询问的内容是完全愚蠢的,任何想要在生产代码中尝试这样的事情的人都应该被解雇和/或开枪.我主要是想看看是否可以做到.
现在已经不在了,有没有办法从类外部访问C++中的私有类成员?例如,有没有办法用指针偏移来做到这一点?
(天真和其他非生产准备技术欢迎)
正如评论中所指出的,我问了这个问题,因为我想写一篇关于过度封装的博客文章(以及它如何影响TDD).我想看看是否有办法说"使用私有变量不是100%可靠的方法来强制封装,即使在C++中也是如此." 最后,我决定更多地关注如何解决问题,而不是为什么这是一个问题,所以我没有像我原先计划的那样突出显示这里提到的一些东西,但我还是留下了一个链接.
无论如何,如果有人对它的出现感兴趣,那么它就是: 测试驱动开发的敌人第一部分:封装(我建议在你决定我疯了之前阅读它).
C++标准在注释14.7.2/12 [temp.explicit]中声明了以下内容:
通常的访问检查规则不适用于用于指定显式实例化的名称.[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是通常不可访问的私有类型或对象,模板可能是成员模板或成员函数通常无法访问. - 结束说明]
如果我可以实例化它,我希望可以使用模板.
我尝试使用gcc-4.8.2,当我访问显式命名类的私有成员时,我得到了预期的行为.但是,当我通过模板参数访问私有成员时,访问检查规则确实适用.这是gcc中的错误,还是我错过了什么?
在下面的代码中,'succeeded'和'failed'之间的唯一区别是前者通过'A'直接访问私有成员,而后者通过模板参数'T'访问它.编译器抱怨privateFoobar在该上下文中是私有的.
#include <iostream>
#include <string>
struct A
{
private:
std::string privateFoobar() {return "private foobar!";}
};
typedef std::string (A::*Foobar)();
template <class Type, Type value>
struct Access
{
static Type getValue() {return value;}
};
template <class T>
struct IndirectAccess
{
static Foobar succeeds() {return Access<Foobar, &A::privateFoobar>::getValue();}
static Foobar fails() {return Access<Foobar, &T::privateFoobar>::getValue();}
};
template class Access<Foobar, &A::privateFoobar>;
int main() {
std::cout << (A().*Access<Foobar,&A::privateFoobar>::getValue())() << std::endl;
std::cout << (A().*IndirectAccess<A>::succeeds())() << std::endl;
std::cout << (A().*IndirectAccess<A>::fails())() << std::endl; …Run Code Online (Sandbox Code Playgroud)