面试问题的网站有以下问题:
class Something {
public:
Something() {
topSecretValue = 42;
}
bool somePublicBool;
int somePublicInt;
std::string somePublicString;
private:
int topSecretValue;
};
有必要[在不触及原始类的情况下]获取 的值topSecretValue。这是解决方案:
class SomethingReplica {
public:
int getTopSecretValue() { return topSecretValue; }
bool somePublicBool;
int somePublicInt;
std::string somePublicString;
private:
int topSecretValue;
};
int main(int argc, const char * argv[]) {
Something a;
SomethingReplica* b = reinterpret_cast<SomethingReplica*>(&a);
std::cout << b->getTopSecretValue();
}
我的问题是,这样的解决方案有效吗?我们可以转换为任意类吗?如果没有,这个问题是否有有效的解决方案?
0号:德拉图蒂
实例化模板时不使用访问检查。
在线编译器
在这里,来自Sutter - 当时各种 C++03 方式 :)
考虑以下头文件。
显示任意调用代码如何直接访问
private_.罪魁祸首 #1:伪造者
伪造者的方法是复制被伪造的类的定义,并进行我们需要的所有更改,例如:
当然,这样做是不合法的。这是非法的,只是因为它违反了单一定义规则,该规则表示如果一个类型(在我们的例子中,
X)被定义了不止一次,那么它的所有定义都必须相同。上面示例中使用的对象,虽然它的名称X和外观类似于,但与程序代码的其余部分使用的对象X不同。X然而,这种“hack”适用于大多数编译器,因为对象数据的位置将保持不变。罪魁祸首 #2:扒手
扒手会安静地工作——替换类定义的含义,例如,如下所示。
这个人是个扒手。记住他灵巧的手指!
当然,扒手的所作所为是不合法的。例 15-2 中的代码不可移植有两个原因。
用指令重新定义保留字是不合法的
#define。 在这种情况下,与伪造者的情况一样,同样违反了一个定义的规则。但是,如果对象数据的位置保持不变,则此方法将起作用。
罪魁祸首 #3:欺诈者
骗子的作案原理是概念代入。
这个人是个骗子。好好记住!他的广告只是为了把你拖进店里,即使在那里他也一定会设法卖给你一个完全不同的东西,这是广告中讨论的,甚至比其他任何地方都贵几倍。
当然,骗子的所作所为是不合法的。例 15-3 中的代码是非法的有两个原因。
不能保证对象
X在BaitAndSwitch内存中的位置是相同的——尽管在实践中通常是这样。 结果
reinterpret_cast是未定义的,尽管大多数编译器会完全按照诈骗者的要求去做。毕竟,通过说出神奇的词reinterpret_cast,你迫使编译器相信你并对你准备的欺诈行为视而不见。Grata Persona #4:律师
与(其他)罪犯相比,我们中的许多人并非没有理由更害怕衣冠楚楚、面带微笑的律师。
考虑以下代码。
这个人是个知道所有漏洞的律师。他不可能被抓到,因为他太过小心翼翼,既违反了法律条文又违反了法律精神。记住并避免这样的不绅士。
尽管我很想说“当然,律师做的是不合法的”,唉,我不能这样做,因为在最后一个例子中所做的一切都是合法的。为什么?示例 15-4 使用了我有一个成员函数模板的事实
X。提供的代码遵循标准,以便后者保证它将按预期工作。我们在生产中(只是嘘!)做这样的事情。
这类似于 @user7860670 的回答,但完全在编译时工作(可以在
constexpr-expressions 中使用),并且不会产生额外的运行时变量。用法:
执行: