views:

281

answers:

7

This question isn't meant to sound as blatantly insulting as it probably is right now.

This is a homework assignment, and the spec sheet is scarce and poorly designed to say the least. We have a function:

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

Sound simple enough? It should be, but the class GasStation comes with no function that accesses the private variable MaxFuel. So how can I access it anyway using the function refuel?

I'm not considering creating a function setFuel( int liter ) because the teacher always complains rather energetically if I change his specification. So... I guess I have to do some sort of hack around it, but I'm not sure how to go about this without explicitely changing the only function in GasStation and giving it a parameter so that I can call it here.

Any hints perhaps?

+3  A: 

Declare refuel(..) as a friend function. Otherwise, you are out of luck.

AraK
+9  A: 

Now that sounds like a real lousy homework assignment.

Anyway, I can think of three ways to access private data:

  1. through public member functions
  2. by a friend of the class
  3. cheating:
    #define private public 
    #include "the_class.h"
    #undef private

The first two are legal, but require you to change the class. The last is "non-intrusive" (for some definition of "non-intrusive", anyway), but is definitely illegal (although I have yet to see a compiler were it wouldn't work).

sbi
#3 is dirty! I'd not seen that before :)
Michael Dorgan
Of course, there's always type-punning. This is also "cheating" and undefined, of course.
Matthew Flaschen
+1 for the lol's
BlueRaja - Danny Pflughoeft
@Michael You could have seen it [yesterday](http://stackoverflow.com/questions/3002101/how-can-i-violate-encapsulation-property/3004223#3004223) ;-)
FredOverflow
+1  A: 

This is dirty, but you can do:

#define private public
#include "GasStation.h" // Or whatever the name is

Now the compiler thinks everything in that header is public. Joy!

James Roth
+2  A: 

I have a suitably terrible solution for your teacher's terrible assignment.

#define private public
#include "GasStation.h"
#undef private
zildjohn01
Please don't encourage him! LOL A friend is a better option!
Lirik
+1  A: 

Best way is to add public member function to GasStation.

Something less safe is to make refuel a friend function.

Absolutely not safe option is available if you know offset of member MaxFuel in that class. Then you could change it as follows (NEVER DO THIS IN PRODUCTION CODE):

int* max_fuel = reinterpret_cast<int*>( reinterpret_cast<char*>(gs)+MaxFuel_OFFSET );
*max_fuel = new_value;
Kirill V. Lyadvinsky
Did you not mean `*max_fuel = new_value;` ?
VDVLeon
Yes, thank you.
Kirill V. Lyadvinsky
+2  A: 

Compile and run a test program. Run it in a debugger and examine the memory layout of GasStation. calculate the exact distance in bytes what the distance from the start of a GasStation to the int you need to set is (note if it's the first thing and there's no virtual functions then that distance is guaranteed to be 0 so you can omit the first few steps).

Use this value to increment the pointer to the position within the object where you need to set the data as Kirill shows. However, just to be an ass--your teacher deserves it--do not use any symbolic language here...use the value of the distance directly like so:

*reinterpret_cast<int*>(reinterpret_cast<char*>(gs)+42);

or whatever 42 should be to get to the right place.

If you really want to be an ass, put a fake variable in your function. Compile and run the program and then find the distance on the stack between this fake variable and the location of the GasStation pointer data. Then do this:

*reinterpret_cast<int*>(reinterpret_cast<char*>(*reinterpret_cast<char**>(reinterpret_cast<char*>(&my_var)-666)) + 42) = new_value;
Noah Roberts
+1  A: 

Obviously the point of a GasStation is to offer GasStation::pump(Car&). This will decrement private: unsigned int MaxFuel for you.

MSalters