这个问题并不意味着听起来像现在可能是侮辱性的。
这是一项家庭作业,规格表缺乏设计,设计不佳至少可以说。我们有一个功能:
double refuel( int liter, GasStation *gs )
{
// TODO: Access private variable MaxFuel of gs and decrement.
}
声音够简单?它应该是,但GasStation类没有访问私有变量MaxFuel的功能。那么我怎样才能使用函数加油来访问它?
我不打算创建一个函数setFuel( int liter )
,因为如果我改变他的规范,老师总是抱怨相当有力。所以...我想我必须做一些黑客攻击,但我不知道如何在没有明确改变GasStation中的唯一功能并给它一个参数的情况下解决这个问题,这样我就可以在这里调用它。 / p>
也许有任何提示?
答案 0 :(得分:16)
现在听起来像是一个真正糟糕的家庭作业。
无论如何,我可以想到三种访问私人数据的方法:
friend
作弊:
#define private public
#include "the_class.h"
#undef private
前两个是合法的,但要求您更改课程。最后一个是“非侵入性的”(对于某些“非侵入性”的定义,无论如何),但绝对是非法的(虽然我还没有看到编译器它不起作用)。
答案 1 :(得分:3)
将refuel(..)
声明为朋友功能。否则,你运气不好。
答案 2 :(得分:3)
编译并运行测试程序。在调试器中运行它并检查GasStation的内存布局。计算从GasStation开始到你需要设置的int的距离的确切距离(注意它是否是第一个并且没有虚函数,那么该距离保证为0所以你可以省略前几个步)。
使用此值将指针递增到对象中您需要设置数据的位置,如Kirill所示。然而,只是为了成为一个屁股 - 你的老师应得的 - 不要在这里使用任何符号语言......直接使用距离的值:
*reinterpret_cast<int*>(reinterpret_cast<char*>(gs)+42);
或任何42应该到达正确的地方。
如果你真的想成为一个屁股,请在你的函数中添加一个假变量。编译并运行程序,然后在该假变量和GasStation指针数据的位置之间找到堆栈上的距离。然后这样做:
*reinterpret_cast<int*>(reinterpret_cast<char*>(*reinterpret_cast<char**>(reinterpret_cast<char*>(&my_var)-666)) + 42) = new_value;
答案 3 :(得分:2)
对于老师糟糕的任务,我有一个非常糟糕的解决方案。
#define private public
#include "GasStation.h"
#undef private
答案 4 :(得分:2)
GasStation
显然要提供GasStation::pump(Car&)
。这将为您减少private: unsigned int MaxFuel
。
答案 5 :(得分:1)
这很脏,但你可以这样做:
#define private public
#include "GasStation.h" // Or whatever the name is
现在编译器认为该标头中的所有内容都是公开的。快乐!
答案 6 :(得分:1)
最好的方法是将公共成员函数添加到GasStation
。
不太安全的是让refuel
成为朋友的功能。
如果您知道该类中成员MaxFuel
的偏移量,则绝对不安全的选项可用。然后你可以改变如下(从不在生产代码中这样做):
int* max_fuel = reinterpret_cast<int*>( reinterpret_cast<char*>(gs)+MaxFuel_OFFSET );
*max_fuel = new_value;