Как получить доступ к частной переменной?

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

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

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

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

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

Какие-нибудь намеки?


person IAE    schedule 10.06.2010    source источник
comment
Частные переменные созданы не для доступа. Что за домашнее задание!   -  person kennytm    schedule 11.06.2010
comment
Позвольте мне уточнить это. Вкратце, ваше назначение, учитывая конкретный класс, который вы не можете изменить, заключается в конкретном доступе и изменении частного члена, у которого нет методов доступа, извне определения класса?   -  person zildjohn01    schedule 11.06.2010
comment
Ух ты. Передача указателя на голый класс в функцию для доступа к частной переменной. Ик. Есть ли какой-нибудь метод get () для значения MaxFuel, на которое вы смотрите, или, возможно, есть перечисление или константа, которые вы должны получить? Если бы это было дано нескольким студентам, я бы подумал, что эта проблема уже возникла бы.   -  person Michael Dorgan    schedule 11.06.2010
comment
Помните детей: только друзья могут трогать ваши интимные места.   -  person Ben Burnett    schedule 11.06.2010
comment
Этого инструктора нужно буксировать на киле.   -  person Amardeep AC9MF    schedule 11.06.2010
comment
Что ж, ознакомьтесь с мнением Херба Саттера @ gotw.ca/gotw/076.htm ; особенно «Решение языкового юриста» :-)   -  person Abhay    schedule 11.06.2010
comment
@ zildjohn01: да @ Дорган: Нет, как уже говорилось, всех спецификаций крайне мало. Ни перечисления, ни наследования, ни дружественных функций. @ Abhay: Спасибо за ссылку!   -  person IAE    schedule 11.06.2010
comment
@SoulBeaver: так, согласно статье Саттера, на которую указал Абхай, ключ (в любом случае к решению, соответствующему стандарту) заключается в том, имеет ли класс GasStation шаблон члена, который может быть специализирован. в противном случае похоже, что вы застряли с одним из «нелегальных» уловок.   -  person Michael Burr    schedule 11.06.2010


Ответы (7)


Это звучит как ужасное домашнее задание.

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

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

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

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

person sbi    schedule 10.06.2010
comment
№3 грязный! Я такого раньше не видел :) - person Michael Dorgan; 11.06.2010
comment
Конечно, всегда есть каламбур. Это тоже жульничество и, конечно, неопределенное. - person Matthew Flaschen; 11.06.2010
comment
@Michael Вы могли видеть это вчера ;-) - person fredoverflow; 11.06.2010
comment
+1. 3) действительно помог мне отладить OpenCV без перестройки библиотеки. - person Emiswelt; 21.10.2015

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

person AraK    schedule 10.06.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;
person Edward Strange    schedule 10.06.2010

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

#define private public
#include "GasStation.h"
#undef private
person zildjohn01    schedule 10.06.2010
comment
Пожалуйста, не поощряйте его! LOL Друг - лучший вариант! - person Kiril; 11.06.2010

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

person MSalters    schedule 11.06.2010

Это грязно, но вы можете:

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

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

person James Roth    schedule 10.06.2010
comment
Это ошибка компилятора или просто проверка в одном из заголовков MS? - person James Roth; 24.09.2013

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

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

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

int* max_fuel = reinterpret_cast<int*>( reinterpret_cast<char*>(gs)+MaxFuel_OFFSET );
*max_fuel = new_value;
person Kirill V. Lyadvinsky    schedule 10.06.2010
comment
Вы не имели в виду *max_fuel = new_value;? - person VDVLeon; 11.06.2010