如何访问私有变量?

时间:2010-06-10 20:23:53

标签: c++ class private

这个问题并不意味着听起来像现在可能是侮辱性的。

这是一项家庭作业,规格表缺乏设计,设计不佳至少可以说。我们有一个功能:

double refuel( int liter, GasStation *gs )
{
    // TODO: Access private variable MaxFuel of gs and decrement.
}

声音够简单?它应该是,但GasStation类没有访问私有变量MaxFuel的功能。那么我怎样才能使用函数加油来访问它?

我不打算创建一个函数setFuel( int liter ),因为如果我改变他的规范,老师总是抱怨相当有力。所以...我想我必须做一些黑客攻击,但我不知道如何在没有明确改变GasStation中的唯一功能并给它一个参数的情况下解决这个问题,这样我就可以在这里调用它。 / p>

也许有任何提示?

7 个答案:

答案 0 :(得分:16)

现在听起来像是一个真正糟糕的家庭作业。

无论如何,我可以想到三种访问私人数据的方法:

  1. 通过公共成员职能
  2. 由班级的friend
  3. 作弊:

    #define private public 
    #include "the_class.h"
    #undef private
    
  4. 前两个是合法的,但要求您更改课程。最后一个是“非侵入性的”(对于某些“非侵入性”的定义,无论如何),但绝对是非法的(虽然我还没有看到编译器它不起作用)。

答案 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;