Комментарии 25
Паблик Морозов жив.
+22
Давайте еще скажем, что кто-то не знал, что компилятору с -O3 или -Ofast вообще всё равно на ООП.
+4
#define protected public
# include <external_header>
#undef protected
+10
НЛО прилетело и опубликовало эту надпись здесь
Интересный вариант! Причем и для private-членов должно сработать.
Но есть один недостаток: то для «взлома» мне нужно было самому осознанно писать имя макроса, а ваше делает видимым вообще все и без макросов.
Мне все же больше понравился вариант с using.
Но есть один недостаток: то для «взлома» мне нужно было самому осознанно писать имя макроса, а ваше делает видимым вообще все и без макросов.
Мне все же больше понравился вариант с using.
-1
Есть еще проще метод, многие компиляторы разрешают взятие адреса для методов не проверяя атрибуты доступа, так что можно еще и так.
+1
Увы, многие компиляторы следуют стандарту
test.cpp(11): error C2248: 'A::f': cannot access protected member declared in class 'A'
auto x = &A::f;
test.cpp(11): error C2248: 'A::f': cannot access protected member declared in class 'A'
0
Тогда еще можно встроенный ассемблер призвать на помощь, ну и еще немного разврату — мы люди без комплексов, можем и знаем толк как потрогать неприкасаемое так что б приятно компилируемо было.
#include <iostream>
using namespace std;
class A
{
int t;
void printT()
{
cout<<"t="<<t<<endl;
};
int alpha()
{
cout<<this<<"->alpha()"<<endl;
this->printT();
return 0;
}
public:
A():t(0){;}
void setT(int _){this->t = _;}
};
class B
{
virtual int beta()
{
cout<<this<<"->beta()"<<endl;
return 0;
}
public:
virtual void gamma(){};
};
class C:public B
{
public:
int beta(){return 0;};
private:
void gamma(){cout<<"Private function of class C "<<this<<"->gamma() called"<<endl;}
};
int main()
{
A e;
e.setT(800);
__asm
{
lea edx, A::alpha
lea ecx, e
call edx
}
C* e2 = (C*)new B;
e2->beta();
delete e2;
B* e3 = new C;
e3->gamma();
delete e3;
return 0;
}
Это в студии 2008 работало.
+1
.
+4
Если в классе есть хоть один шаблонный метод, то можно и private-члены вытащить, написав его специализацию для какого-нибудь dummy-типа. Выйдет еще "красивее".
0
Другой вариант с наследованием:
class A
{
protected:
void f() {}
};
class B: public A
{
public:
A::f;
};
int main()
{
B b;
b.f();
return 0;
}
+3
Не обязательно задавать параметры метода, можно сделать проще с помощью using.
class A
{
protected:
int f() { return 0; }
};
class B : public A
{
public:
using A::f;
};
A a;
static_cast<B&>(a).f();
+5
class B: public A {
public: using A::f;
};
+6
Такое преобразование является неопределённым поведением. Даже если прямо сейчас это работает, нет никакой гарантии, что поведение не изменится в самом ближайшем будущем.
Подробнее про то, почему это UB можно посмотреть на stackoverflow (теория)(похожий пример)
Подробнее про то, почему это UB можно посмотреть на stackoverflow (теория)(похожий пример)
+2
del
0
Кажется, есть простое решение, вообще не использующее грубых приведений типов.
Работает вроде бы в любом компиляторе, C++11 тоже не требуется.
В студии работает и A::f вместо B::f.
Работает вроде бы в любом компиляторе, C++11 тоже не требуется.
static int _f(A &a){ return (a.*&B::f)(); }
В студии работает и A::f вместо B::f.
0
В студии работает и A::f вместо B::f.Проверил в 2015-й:
static int _f(A &a){ return (a.*&A::f)(); }
test.cpp(8): error C2248: 'A::f': cannot access protected member declared in class 'A'
зы. А, этот
static int _f
нужно поместить внутрь класса B. Но от создания лишнего класса не уходим ((0
Ну да, это поправка к тому, что в статье называется Идея 1. То есть дополнительный класс B со статическим методом, но без каких-либо грубых преобразований типов.
А по этой ссылке можно найти (более извращенный) способ достучаться и до приватных полей и функций. Там еще в комментариях полезные ссылки.
А по этой ссылке можно найти (более извращенный) способ достучаться и до приватных полей и функций. Там еще в комментариях полезные ссылки.
0
Если у Вас метод protected, зачем все так сложно? Почему нельзя унаследоваться от A и работать уже с классом-наследником?
+1
Работа с целевым классом в используемой мной библиотеке ведется не напрямую, а через еще один класс.
Потоки из стандартной библиотеки устроены таким образом, что сначала реализуется наследник std::streambuf, а потом он используется в другом классе, наследующем std::iostream. Чтобы правильно внедрить свой streambuf, пришлось бы разбираться еще и в классе-наследнике iostream.
Если знаете способ обойти это, буду признателен за совет.
Потоки из стандартной библиотеки устроены таким образом, что сначала реализуется наследник std::streambuf, а потом он используется в другом классе, наследующем std::iostream. Чтобы правильно внедрить свой streambuf, пришлось бы разбираться еще и в классе-наследнике iostream.
Если знаете способ обойти это, буду признателен за совет.
0
Вы можете описать задачу более конкретно?
Потому что в статье ни слова про такие трудности (не считая одного упоминания iostream). В статье Вы просто пишите, что метод, возвращающий файловый дескриптор находится в секции protected.
Потому что в статье ни слова про такие трудности (не считая одного упоминания iostream). В статье Вы просто пишите, что метод, возвращающий файловый дескриптор находится в секции protected.
+1
Попытался построить простую модель решаемой задачи:
Реальные классы можете посмотреть в коде библиотеки. Для решения задачи наследованием нужно внедрить в класс basic_pstream своего наследника basic_pstreambuf.
Код
class TBase {};
class Target : public TBase {
protected: int target_function(){ return 5; }
};
class Base {
private: TBase *tbase;
public: Base(TBase *t) : tbase(t) {}
};
class Main : public Base {
private: Target t;
public:
Main() : Base(&t) {}
const Target &getTarget(){ return t; }
};
int main(){
Main m;
int val = m.getTarget().target_function(); //нужно получить это
}
Реальные классы можете посмотреть в коде библиотеки. Для решения задачи наследованием нужно внедрить в класс basic_pstream своего наследника basic_pstreambuf.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Красиво «взламываем» ООП с помощью C++14