#cpp #классы
Здравствуйте, нашел на неком ресурсе подобный код(немного его модифицировал под себя): #includeusing namespace std; class PrivateClass { public: PrivateClass(int a, char b) : privateInt(a), privateChar(b) {} int getInt() {return privateInt; } char getChar() {return privateChar; } private: int privateInt; char privateChar; }; class Stealer { public: int &stealInt(PrivateClass &clss) { return ((Stealer *) (&clss))->stealedInt; } char &stealChar(PrivateClass &clss) { return ((Stealer *) (&clss))->stealedChar; } private: int stealedInt; char stealedChar; }; int main() { PrivateClass prVar(20, 'a'); Stealer stVar; int &stlInt = stVar.stealInt(prVar); char &stlChar = stVar.stealChar(prVar); cout << "Private Class:\nInt = " << prVar.getInt() << "\nChar = " << prVar.getChar() << endl; cout << "\nStealed:\nInt = " << stlInt << "\nChar = " << stlChar << endl; stlInt = -65; stlChar = 'q'; cout << "Int = " << stlInt << "\nChar = " << stlChar << endl; cout << "\nPrivate Class:\nInt = " << prVar.getInt() << "\nChar = " << prVar.getChar() << endl; return 0; } Результат: Private Class: Int = 20 Char = a Stealed: Int = 20 Char = a Int = -65 Char = q Private Class: Int = -65 Char = q Как я понял, класс Stealer как-то получил доступ к закрытым полям класса PrivateClass да ещё и по ссылке, что дало возможность менять значения переменной "извне". Увы, я внятного ответа нигде не нашел. Что это может быть?
Ответы
Ответ 1
Тут все совершенно тривиально, что может и быть причиной того, что объяснения отсутствуют. Класс Stealer просто переинтерпретирует память объекта типа PrivateClass как память объекта типа Stealer. Расположение полей класса Stealer, согласно задумке, должно совпадать с расположением полей класса PrivateClass. Это означает, что, согласно задумке, после такой переинтерпретации, смотря через поля класса Stealer, мы будем "видеть" в памяти соответствующие поля класса PrivateClass. Подобные трюки нарушают требования strict aliasing языка C++. Код порождает неопределенное поведение и в общем случае неработоспособен. P.S. Прием, позволяющий легально обойти защиту, предоставляемую private я приводил вот здесь: https://ru.stackoverflow.com/a/656542/182825. В применении к данному случаю: http://coliru.stacked-crooked.com/a/49db7cfe2b1bc36bОтвет 2
Грязный хак :) Просто сделан аналогичный по структуре класс, и область памяти, занятая одним классом, объявлена как область памяти, занятая другим классом, который позволяет обратиться к его данным, а уж открытые они там или закрытые... Класс не "получил доступ", он подменил объект другого класса собой. Вернее, даже не объект, а указатель на объект другого класса объявил, как указатель на объект своего класса - с такой же внутренней структурой. Грубо говоря, подделал паспорт :)
Комментариев нет:
Отправить комментарий