Есть учебное задание, в котором необходимо получить доступ к 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-коде. Думаю, будет поучительно, если вы отправите ссылку на это обсуждение вашему преподавателю.
Комментариев нет:
Отправить комментарий