dobranie się do prywatnych zmiennych

0

Chce się dobrać do zmiennych prywatnych w klasie w pewniej lib bez zmiany kodu tej biblioteki, api nie daje mi zadnych możliwosci

class base
{
	int x = 42;
};
class kl : private base
{
	int test()
	{
		return base::x;
	}
};

Czy jest jakiś sposób?

2

Nie da się. O to chodzi w private.

Są dwie niemądre metody.

Pierwsza:

#define private public
#include "TaTwojaKlasa.hpp"
#undef private

albo:

#define class struct
#include "TaTwojaKlasa.hpp"
#undef class

(Co dziwne, ta bzdura powyżej jest dopuszczalna o ile nie includuje się nagłówków z biblioteki standardowej - w nich nie można zamieniać słów kluczowych za pomocą makr, 17.6.4.3.1.2)

Druga to dobieranie się do składników klasy za pomocą arytmetyki wskaźników. To jest pewny undefined behavior wg standardu, ale o ile klasa jest prosta powinno to jakoś działać.

0

Teoretycznie czy praktycznie?
Teoretycznie to nie i są ku temu powody -> skoro twórca biblioteki oznaczył to jako prywatne to znaczy że uważa że nikt nie powinien przy tym majstrować. Może na przykład inne elementy biblioteki opierają się o pewne niepisane zasady co do wartości takich prywatnych pól i ich zmiana będzie powodować trudne do wykrycia błędy? To jest bardzo ryzykowna sprawa i raczej odradzam.
Praktycznie w C++ niewiele jest rzeczy których zrobić nie można. Na dobrą sprawę obiekt danej klasy to są po prostu pewne bajty interpretowane w odpowiedni sposób. Jeśli klasa nie ma metod wirtualnych (czyli tym samym tablicy virtual methods pointers) i nie ma pól bitowych (więc potencjalnych paddingów) to można sobie łatwo policzyć które bajty z tego obiektu odpowiadają tej twojej zmiennej. Bo pola są zwykle ustawiane po kolei (chyba że masz gdzieś wirtualnej dziedziczenie). Więc nic nie stoi na przeszkodzie żeby zrobic wskaźnik, pokazać nim na obiekt klasy, przesunąć wskaźnik o X bajtów na pozycje gdzie zaczyna sie twoja zmienna, zrzutować na inta, przypisać nową wartość i voila.

edit1: tak jak napisał @Endrju to jest generalnie UB niemniej jest spora szansa że zadziała ;]

edit2: Przykład jak to działa

#include <iostream>
using namespace std;

class A{
    public:
        A(int xx, int yy, int zz):x(xx),y(yy),z(zz){}
        int getX(){return x;}
        int getY(){return y;}
        int getZ(){return z;}
    private:
        int x;
        int y;
        int z;
};

int main(){

    A obiekt = A(1,2,3);
    cout<<obiekt.getX()<<" "<<obiekt.getY()<<" "<<obiekt.getZ()<<endl;
    char* wskaznikByte = (char*) &obiekt;
    int* wskaznikInt = (int*) wskaznikByte;
    *wskaznikInt = 4;
    cout<<obiekt.getX()<<" "<<obiekt.getY()<<" "<<obiekt.getZ()<<endl;
    wskaznikInt = (int*)(wskaznikByte+sizeof(int));
    *wskaznikInt = 5;
    cout<<obiekt.getX()<<" "<<obiekt.getY()<<" "<<obiekt.getZ()<<endl;
    wskaznikInt = (int*)(wskaznikByte+2*sizeof(int));
    *wskaznikInt = 6;
    cout<<obiekt.getX()<<" "<<obiekt.getY()<<" "<<obiekt.getZ()<<endl;
    return 0;
}

1

Jeśli klasa ma szablonową metodę to zawsze możesz napisać jej specjalizację i wtedy masz dostęp do jej zmiennych prywatnych i nie jest to UB.
Więcej w tym temacie znajdziesz tutaj: http://www.gotw.ca/gotw/076.htm

1 użytkowników online, w tym zalogowanych: 0, gości: 1