Страницы

Поиск по вопросам

суббота, 6 октября 2018 г.

Как получить доступ к private-полям класса извне?

Есть учебное задание, в котором необходимо получить доступ к private-полям класса извне. struct Cls дана изначально. Я нагуглил что нужно создать копию структуры, но с public методами, а потом через нее стучаться в изначальную. Вопрос в том как это реализовать? Как можно вернуть ссылку на private поля?
struct Cls { Cls(char c, double d, int i); private: char c; double d; int i; };

struct B { B(char c, double d, int i); public: char c1; double d1; int i1; };
// Эта функция должна предоставить доступ к полю c объекта cls. // Обратите внимание, что возвращается ссылка на char, т. е. // доступ предоставляется на чтение и запись. char &get_c(Cls &cls) {
return ((B*)(&cls))->c1 = 'p';
}
// Эта функция должна предоставить доступ к полю d объекта cls. // Обратите внимание, что возвращается ссылка на double, т. е. // доступ предоставляется на чтение и запись. double &get_d(Cls &cls) { /* ... */ }
// Эта функция должна предоставить доступ к полю i объекта cls. // Обратите внимание, что возвращается ссылка на int, т. е. // доступ предоставляется на чтение и запись. int &get_i(Cls &cls) { /* ... */ }
int main() { Cls cls('h', 2.0, 3); char ch = get_c(&cls); cout << ch << endl; }


Ответ

Вы не можете честным и надёжным путём получить доступ к приватным данным. Существуют грубые хаки, наподобие «угадать бинарный лэйаут данных и скастить указатель», которые прямо запрещены стандартом, и дают право компилятору наказать вас в любой момент.
Правильный ответ на вопрос, как получить доступ к приватным данным — никак. Ваш преподаватель либо задаёт вопрос с подвохом, либо плохо знает язык, который преподаёт.
Конкретно в вашем случае, код
(B*)(&cls)->c1
нарушает strict aliasing rule (правило 3.10/10 стандарта).
Дополнительное чтение по теме:
What is the strict aliasing rule? GotW #76: Uses and Abuses of Access Rights

Окей, исходя из развернувшейся дискуссии в ответе @Vlad from Moscow, вопрос о доступе через указатель на «чужой» тип не так уж очевиден даже из стандарта. Как видите, мы покамест не пришли к общему мнению о том, правомерен ли такой доступ по стандарту. В любом случае, доступ к приватным полям — очень плохой стиль программирования, и даже если так возможно сделать, делать этого не нужно

Обновление: Другие ответы: ([1], [2] и [3]) убедили меня в том, что к приватным полям таки можно получить доступ «законным» — то есть, совместимым со стандартом путём. (Впрочем, с трактовкой стандарта в последнем из них я не вполне согласен, но это лишь показывает, что сам по себе стандарт — достаточно большой и не очень ясно написанный текст.)
Тем не менее, любой из приведённых подходов кажется мне грубым хаком, и я бы крайне не рекомендовал пользоваться ими в production-коде. Думаю, будет поучительно, если вы отправите ссылку на это обсуждение вашему преподавателю.

Комментариев нет:

Отправить комментарий