Каким образом можно получить доступ к приватным полям класса? При этом не используются аксессоры и классы-друзья.
-
Глубоко-глубоко было запрятано объявление друга, еще и использование множественного наследования. В общем, вопрос можно закрывать. Но так писать нельзя. – Стас Литвиненко Dec 30 '11 at 06:30
4 Answers
Известно 3 способа сделать то, о чем вы просите.
- Задефайнить
#define private publicи подключить соответствующий заголовочный файл (естественно, бессмысленно в случаеPIMPL-подобных схем). - Напрямую обращаться по предполагаемому адресу переменной (этот способ вам уже рассказали ). Плох тем, что в зависимости от присутствия в классе
vfptrиvcbl, относительное смещение может меняться, т.е способ непортабельный. - Воспользоваться трюком с
template. Самое красивое и даже в некотором плане элегантное решение.
- 23,562
Только через адреса этих полей.
#include <iostream>
class A
{
private:
int a;
virtual int b ()
{
return a;
}
};
class B
{
public:
int a;
virtual int b ();
};
int main()
{
A obj;
B* ptr = static_cast<B*>(static_cast<void*>((&obj)));
ptr->a = 42;
std::cout<<ptr->b()<<std::endl;
return 0;
}
- 3,255
- 17
- 32
-
Нет, обращение идет по имени поля. Как-то это реализовано через указатель и метод с модификатором static. Плюс наследование. – Стас Литвиненко Dec 28 '11 at 15:15
-
-
Такой метод уже находил. Но немного не похож на данный случай. Тут у меня есть static метод, который возвращает указатель на класс. Вызывая этот метод, я получаю доступ к приватным полям. Явное нарушение принципа инкапсуляции и стандарта плюсов или я чего-то недопонимаю. – Стас Литвиненко Dec 28 '11 at 15:29
Можно вот так:
class A
{
public:
A(int _a) : a(_a) {}
private:
int a;
};
class B
{
public:
B(int _b) : b(_b) {}
public:
int b;
};
int main(int argc, char argv[])
{
A a(0);
((B)(&a))->b = 1; // A.a = 1
return 0;
}
То есть, написав параллельно полную копию этого класса, сделав нужные поля пабликовыми.
- 464
-
-
Ну ведь приватные поля и предназначены для того, чтобы к ним не было доступа помимо аксессоров / методов класса. То, о чём Вы спрашиваете - само по себе явное нарушение стандартов плюсов (насколько я понимаю :). – ASten Dec 28 '11 at 17:15
-
Проблема в том, что это каким-то образом реализовано в библиотеке на работе. Переписывать этот кусок под стандарт не дадут. Вот и пытаюсь понять, как реализовано. Человек, который это писал, уже не работает в том месте. – Стас Литвиненко Dec 28 '11 at 21:53
-
"Вызывая этот метод, я получаю доступ к приватным полям" - поясните, как это происходит. Было бы легче, если бы вы привели исходники этого дела, хотя бы часть, и то место, которое вас смущает. – ASten Dec 29 '11 at 16:12
-
В данном случае, если в структуре один член, можно написать так: ((int)&a)=5; – devoln Dec 30 '11 at 07:16
Недавно у самого была похожая проблема. Изобрёл новый способ. Не знаю подойдёт он тебе или нет. Если у этого класса есть хотя бы один друг(неважно какой, доступный тебе в коде или нет) то ты можешь объявить свой класс с именем, что и имя друга. Пример:
В файле Graphics.h:
class Material;
class Graphics
{
public:
Material* CreateMaterial(Color color)
{
Material* material=new Material;
material->color=color;
return material;
}
};
В файле Material.h:
class Material
{
friend class Graphics;
private:
Color color;
};
Допустим, у тебя был такой код и ты его не трогаешь. И тут вдруг мы в файле main.cpp объявляем самозванца Graphics:
#include "Material.h"
class Graphics
{
static void ChangeMaterialColor(Material* material, Color newcolor)
{
material->color=newcolor;
}
};
Теперь мы можем менять цвет материала при помощи такого самозванца-друга. Единственный момент: два определения Graphics не должны быть объявленыподключены в один cpp-файл, иначе они будут конфликтовать. В моём примере это соблюдается: Material не подключает Graphics, а довольствуется его объявлением.
- 5,441