Как получить доступ к закрытой переменной? - PullRequest
0 голосов
/ 11 июня 2010

Этот вопрос не должен звучать столь вопиюще оскорбительно, как сейчас, наверное.

Это домашнее задание, а спецификация скудна и плохо разработана, чтобы не сказать больше.У нас есть функция:

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

Звучит достаточно просто?Так и должно быть, но класс GasStation не имеет функции, которая обращается к закрытой переменной MaxFuel.Так как же я могу получить к нему доступ, используя функцию заправки?

Я не рассматриваю создание функции setFuel( int liter ), потому что учитель всегда довольно энергично жалуется, если я изменяю его спецификацию.Итак ... я думаю, что мне нужно сделать что-то вроде хака, но я не уверен, как это сделать без явного изменения единственной функции в GasStation и присвоения ей параметра, чтобы я мог вызвать ее здесь.

Возможно, есть намеки?

Ответы [ 7 ]

16 голосов
/ 11 июня 2010

Это звучит как настоящее паршивое домашнее задание.

В любом случае, я могу придумать три способа доступа к личным данным:

  1. через публичного участникафункции
  2. friend класса
  3. обман:

    #define private public 
    #include "the_class.h"
    #undef private
    

Первые два законны, но требуют от васизменить класс.Последний является «не навязчивым» (для некоторого определения «не навязчивый», во всяком случае), но определенно незаконным (хотя я еще не видел компилятор, где бы он не работал).

3 голосов
/ 11 июня 2010

Скомпилируйте и запустите тестовую программу. Запустите его в отладчике и проверьте расположение памяти в GasStation. вычислите точное расстояние в байтах, каково расстояние от начала GasStation до int, которое вам нужно установить (обратите внимание, что если это первое, а виртуальных функций нет, то это расстояние гарантированно будет равно 0, поэтому вы можете пропустить первые несколько шаги).

Используйте это значение для увеличения указателя на позицию в пределах объекта, где вам нужно установить данные, как показывает Кирилл. Однако, просто чтобы быть задницей - ваш учитель этого заслуживает - не используйте здесь какой-либо символический язык ... используйте значение расстояния напрямую, например:

*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 голосов
/ 11 июня 2010

Объявите refuel(..) как функцию друга.В противном случае вам не повезло.

2 голосов
/ 11 июня 2010

Очевидно, что смысл GasStation состоит в том, чтобы предложить GasStation::pump(Car&). Это уменьшит для вас private: unsigned int MaxFuel.

2 голосов
/ 11 июня 2010

У меня есть подходящее ужасное решение для ужасного задания вашего учителя.

#define private public
#include "GasStation.h"
#undef private
1 голос
/ 11 июня 2010

Лучший способ - добавить функцию-член к GasStation.

Что-то менее безопасное - сделать refuel функцией друга.

Абсолютно небезопасная опция доступна, если вы знаете смещение члена MaxFuel в этом классе.Тогда вы можете изменить его следующим образом (НИКОГДА НЕ ДЕЛАЙТЕ ЭТОГО В ПРОИЗВОДСТВЕННОМ КОДЕКСЕ):

int* max_fuel = reinterpret_cast<int*>( reinterpret_cast<char*>(gs)+MaxFuel_OFFSET );
*max_fuel = new_value;
1 голос
/ 11 июня 2010

Это грязно, но вы можете сделать:

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

Теперь компилятор считает все в этом заголовке общедоступным.Радость! * * 1004

...