Управление доступом

299
18 января 2018, 21:19

Как еще можно обойти защищенность полей в ооп? кроме дружественных функций

Answer 1

Если говорить действительно о "взломах защиты", т.е. о способах, которые не требуют кооперации со стороны "взламываемого" класса (т.е. не опираются на изначально заложенные в класс возможности, типа "друзей", методов, возвращающих указатели на члены и т.п.), то одна из малоизвестных "дыр", созданных в языке намеренно - это разрешение для явного инстанциирования шаблона игнорировать ограничения доступа.

В следующем примере мы, не используя никаких "хаков", "друзей" или методов самого класса, обходим защиту доступа к private методу

#include <iostream>
class Private {
  void private_func() { std::cout << "Pwned!" << std::endl; }
};
using PTR = void (Private::*)();
PTR ptr;
template <PTR ptr> struct Exploit {                
  static inline struct D { D() { ::ptr = ptr; } } d;
};
template struct Exploit<&Private::private_func>;
int main() {
  (Private().*ptr)();
}

Ключевой момент этой возможности - в разрешении (данном нам разделом 14.7.2/12 стандарта языка) делать

template struct Exploit<&Private::private_func>;

несмотря на то, что функция Private::private_func является private.

Answer 2

В общем случае? Или в каких-то конкретных?

Читерство типа

#define private public

считаем недостойным настоящего программиста? :) Копирование описания класса из заголовочного файла с добавлением в него, например, дружественной функции - тоже?

Есть вариант с созданием своего класса с аналогичным размещением членов в памяти и reinterpret_cast указателя на один объект в указатель на свой - незаконно, UB, но... обычно вполне прокатывает :)

Например, через указатель - если тот же друг создаст указатель на что-то закрытое и вернет его, типа

class X
{  
private: int y;
friend int* z(X&x) { return &x.y; };
...
int * p = z(x);
*p = 5;

Или это не годится, хотя дружественная функция используется опосредованно?

Вот вариант со специализацией шаблонной функции. Допустим, есть некий класс.

class X
{
public:
    template<typename T>
        void f(const T& t)
    { /* ... */ }
private:
    int p;
};

Специализируем эту функцию...

namespace {
    struct Y{};
}
template<>
void X::f(const Y&)
{
    p = 5;
}

и все. Ловкость рук и никакого мошенничества...

READ ALSO
Перегрузка операторов - уточнение

Перегрузка операторов - уточнение

Почему вот это называется перегрузкой оператора? cout разве не выводит пользовательские типы БЕЗ перегрузки?

330
expected &#39;,&#39; or &#39;;&#39; before &#39;do&#39; Ошибка при компиляции

expected ',' or ';' before 'do' Ошибка при компиляции

Начинаю компилировать и выходит ошибка кода, вот: (недоделал пока)

320
Агрегация - доступ к членам класса

Агрегация - доступ к членам класса

Имеет ли при агрегации класс доступ к protected-полям другого, агрегированного класса?

368
отношение между классами

отношение между классами

Можно ли в классе С выполнить расчет int a / int b и записать результат в переменную класса С int c?

370