C++ 私人会员黑客行为是否定义为行为?
我有以下课程:C++ 私人会员黑客行为是否定义为行为?,c++,casting,private-members,C++,Casting,Private Members,我有以下课程: class BritneySpears { public: int getValue() { return m_value; }; private: int m_value; }; class AshtonKutcher { public: int getValue() { return m_value; }; public: int m_value; }; 这是一个外部库(我无法更改)。我显然无法更改m_value
class BritneySpears
{
public:
int getValue() { return m_value; };
private:
int m_value;
};
class AshtonKutcher
{
public:
int getValue() { return m_value; };
public:
int m_value;
};
这是一个外部库(我无法更改)。我显然无法更改m_value
的值,只能读取它。即使是从英国梨衍生出来的,也行不通
如果我定义以下类怎么办:
class BritneySpears
{
public:
int getValue() { return m_value; };
private:
int m_value;
};
class AshtonKutcher
{
public:
int getValue() { return m_value; };
public:
int m_value;
};
然后做:
BritneySpears b;
// Here comes the ugly hack
AshtonKutcher* a = reinterpret_cast<AshtonKutcher*>(&b);
a->m_value = 17;
// Print out the value
std::cout << b.getValue() << std::endl;
britneyspearsb;
//丑陋的黑客来了
AshtonKutcher*a=重新解释铸件(&b);
a->m_值=17;
//打印出值
这是未定义的行为。每个访问限定符节中的成员都保证按它们出现的顺序排列,但是在访问限定符之间没有这样的保证。例如,如果编译器选择将所有私有成员置于所有公共成员之前,则上述两个类将具有不同的布局
编辑:重温这个旧答案,我意识到我忽略了一个非常明显的点:结构定义每个都只有一个数据成员。成员函数的顺序是不相关的,因为它们对类的布局没有贡献。您可能会发现,两个数据成员都保证位于同一个位置,尽管我不太了解标准,无法确定
但是!您不能在不相关的类型之间取消对重新解释\u cast
结果的引用。仍然是乌兰巴托。至少,这是我读到的,这确实是一本很难理解的书。通常应该避免使用reinterpret\u cast,而且它也不能保证给出正确的解释
另外,为什么要更改私人成员?您可以将原始类包装成一个新类(更喜欢组合而不是继承),并根据需要处理getValue方法。这是未定义的行为,原因如下所述。但有时在集成无法修改的外部代码时,您需要求助于这些东西。一种更简单的方法(同样是未定义的行为)是:
@Marcelo说得对:在不同的访问级别中,成员的顺序是未定义的
但请考虑下面的代码;在这里,
AshtonKutcher
的布局与BritneySpears
完全相同:
class AshtonKutcher
{
public:
int getValue() { return m_value; };
friend void setValue(AshtonKutcher&, int);
private:
int m_value;
};
void setValue(AshtonKutcher& ac, int value) {
ac.m_Value = value;
}
class BritneySpears
{
friend class AshtonKutcher;
public:
int getValue() { return m_value; };
private:
int m_value;
};
class AshtonKutcher
{
public:
int getValue(const BritneySpears & ref) { return ref.m_value; };
};
我相信这可能是有效的C++。
你可能无法修改< <代码> > BLYNYYSPIOS的库,但是你应该能够修改.h头文件。如果是这样,你可以让AshtonKutcher成为英国梨的朋友:
class AshtonKutcher
{
public:
int getValue() { return m_value; };
friend void setValue(AshtonKutcher&, int);
private:
int m_value;
};
void setValue(AshtonKutcher& ac, int value) {
ac.m_Value = value;
}
class BritneySpears
{
friend class AshtonKutcher;
public:
int getValue() { return m_value; };
private:
int m_value;
};
class AshtonKutcher
{
public:
int getValue(const BritneySpears & ref) { return ref.m_value; };
};
<>我不能真的原谅这个技巧,我想我自己从来没有试过,但是它应该是合法定义的C++。 < p>你的代码有一个问题,答案是下面划线。问题来自于对值进行排序
然而,你几乎就在那里:
class AshtonKutcher
{
public:
int getValue() const { return m_value; }
int& getValue() { return m_value; }
private:
int m_value;
};
现在,您有了完全相同的布局,因为您有相同的属性,以相同的顺序声明,并且具有相同的访问权限。。。两个对象都没有虚拟表
因此,诀窍不是更改访问级别,而是添加一个方法:)
当然,除非我错过了什么
我确切地说这是一个维护噩梦?< / P >这个代码可以通过“<代码> > BrnyySpult::GoalValue>>(<)/>代码>和<代码> AsuttKutt::GoValueAudio(/Cuff>)简单地返回0。C++ Eron:哦,我还不够聪明,不能指出C++代码中的错误。我指的是这样一个事实,如果这些类正确地模拟了实际的布兰妮·斯皮尔斯和阿什顿·库彻,那么它们的值必须为0。为什么要访问布兰妮·斯皮尔斯的私人部分?(对不起,我真的很努力,但我就是忍不住。)+1因为在一个行为不明确的例子中使用了
BritneySpears
。+1因为在同一句话中使用了Britney的私处和“丑陋的黑客”。嗯,我只是想知道。我不打算在任何真正的代码中这样做;)由于方法getValue
不是虚拟的,因此您将无法通过扩展类来更改其在现有代码中的行为(基类中的所有现有引用都将调用基类方法,并且派生类中的方法(不是真正重写的)将永远不会被调用)那么,如果BritneySpears
的每个成员都是私人的,而AshtonKutcher
的每个成员都是公共的,那该怎么办?订单能保证吗?@ereOn:只有当它们都在一个访问限定符部分时。有两个部分,都是私有的,仍然会导致未指定的内存布局。我仍然想知道,如果不这样问,如何学习这个。谢谢你的教训!:D@ereOn对于这类内容,唯一确定的方法是阅读和理解标准。即使每个类中的成员在排版上完全相同,但如果它们使用不同的编译器选项或不同的编译器编译,您仍然无法保证实际的内存布局。我们可以使用没有标签“private”的私有成员所以这可能行不通;)@Nick D:虽然(?)@Nick:#定义类结构。不是说我会做那样的事。@Tyler,这是个好消息。尽管如此,如果你混合使用这样的编译器,一般来说,你不是很熟练吗?毕竟C++没有定义的ABI。你不允许定义C++关键字,因此,代码> >定义私有的公共< /代码>不是合法的C++,我们不能保证编译器将为两个不同的类按相同的顺序来排序不同的部分。好吧,我不知道哪种实现会像那样,但仍然如此。谁愿意和布兰妮·斯皮尔斯成为朋友?