Comments 25
Паблик Морозов жив.
Давайте еще скажем, что кто-то не знал, что компилятору с -O3 или -Ofast вообще всё равно на ООП.
#define protected public
# include <external_header>
#undef protected
Есть еще проще метод, многие компиляторы разрешают взятие адреса для методов не проверяя атрибуты доступа, так что можно еще и так.
Увы, многие компиляторы следуют стандарту
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'
Тогда еще можно встроенный ассемблер призвать на помощь, ну и еще немного разврату — мы люди без комплексов, можем и знаем толк как потрогать неприкасаемое так что б приятно компилируемо было.
#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 работало.
.
Если в классе есть хоть один шаблонный метод, то можно и private-члены вытащить, написав его специализацию для какого-нибудь dummy-типа. Выйдет еще "красивее".
Другой вариант с наследованием:
class A
{
protected:
void f() {}
};
class B: public A
{
public:
A::f;
};
int main()
{
B b;
b.f();
return 0;
}
Не обязательно задавать параметры метода, можно сделать проще с помощью using.
class A
{
protected:
int f() { return 0; }
};
class B : public A
{
public:
using A::f;
};
A a;
static_cast<B&>(a).f();
class B: public A {
public: using A::f;
};
Такое преобразование является неопределённым поведением. Даже если прямо сейчас это работает, нет никакой гарантии, что поведение не изменится в самом ближайшем будущем.
Подробнее про то, почему это UB можно посмотреть на stackoverflow (теория)(похожий пример)
Подробнее про то, почему это UB можно посмотреть на stackoverflow (теория)(похожий пример)
del
Кажется, есть простое решение, вообще не использующее грубых приведений типов.
Работает вроде бы в любом компиляторе, C++11 тоже не требуется.
В студии работает и A::f вместо B::f.
Работает вроде бы в любом компиляторе, C++11 тоже не требуется.
static int _f(A &a){ return (a.*&B::f)(); }
В студии работает и A::f вместо B::f.
В студии работает и 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. Но от создания лишнего класса не уходим ((Ну да, это поправка к тому, что в статье называется Идея 1. То есть дополнительный класс B со статическим методом, но без каких-либо грубых преобразований типов.
А по этой ссылке можно найти (более извращенный) способ достучаться и до приватных полей и функций. Там еще в комментариях полезные ссылки.
А по этой ссылке можно найти (более извращенный) способ достучаться и до приватных полей и функций. Там еще в комментариях полезные ссылки.
Если у Вас метод protected, зачем все так сложно? Почему нельзя унаследоваться от A и работать уже с классом-наследником?
Работа с целевым классом в используемой мной библиотеке ведется не напрямую, а через еще один класс.
Потоки из стандартной библиотеки устроены таким образом, что сначала реализуется наследник std::streambuf, а потом он используется в другом классе, наследующем std::iostream. Чтобы правильно внедрить свой streambuf, пришлось бы разбираться еще и в классе-наследнике iostream.
Если знаете способ обойти это, буду признателен за совет.
Потоки из стандартной библиотеки устроены таким образом, что сначала реализуется наследник std::streambuf, а потом он используется в другом классе, наследующем std::iostream. Чтобы правильно внедрить свой streambuf, пришлось бы разбираться еще и в классе-наследнике iostream.
Если знаете способ обойти это, буду признателен за совет.
Вы можете описать задачу более конкретно?
Потому что в статье ни слова про такие трудности (не считая одного упоминания iostream). В статье Вы просто пишите, что метод, возвращающий файловый дескриптор находится в секции protected.
Потому что в статье ни слова про такие трудности (не считая одного упоминания iostream). В статье Вы просто пишите, что метод, возвращающий файловый дескриптор находится в секции protected.
Попытался построить простую модель решаемой задачи:
Реальные классы можете посмотреть в коде библиотеки. Для решения задачи наследованием нужно внедрить в класс 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.
Sign up to leave a comment.
Красиво «взламываем» ООП с помощью C++14