2010-08-08 2 views
10

Будет ли возможность публичной функции возвращать указатель на приватную переменную в классе. Если так/если нет, что произойдет? это будет крушение или есть что-то очень опасное в этом отношении? Можно ли прочитать или записать указанные данные? ThanksДоступ к частной переменной через свой адрес?

ответ

23

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

Элемент данных, безусловно, может быть прочитан через возвращаемый указатель или ссылку. Независимо от того, может ли оно быть записано, зависит от того, является ли возвращаемый указатель или ссылка объекту с контеном (т. Е. Если вы вернете const T*, вы не сможете изменить указатель на T). Например:

class Example 
{ 
public: 
    int*  get()    { return &i; } 
    const int* get_const() const { return &i; } 
private: 
    int i; 
}; 

int main() 
{ 
    Example e; 

    int* p = e.get(); 
    int a = *p; // yes, we can read the data via the pointer 
    *p = 42;  // yes, we can modify the data via the pointer 

    const int* cp = e.get_const(); 
    int b = *cp; // yes, we can read the data via the pointer 
    *cp = 42;  // error: pointer is to a const int   
} 
+1

См. Эффективный C++ Item 28. И +1. –

+0

Этот подход опасен. Он может легко сбрасывать int * x = Example() .get(); удалить x; int * y = Пример().получить(); // Crashes –

+1

@jack london: IMO, на C++, если вы собираетесь вообще заниматься ручным управлением памятью, вы просто не можете называть 'delete' на произвольных указателях и рассчитывать избежать этого. Если вы управляете памятью вручную, вы должны знать, что делаете. – UncleBens

3

Да, он может быть возвращен, и его можно прочитать и записать. Это не более или менее опасно, чем обращение к любой другой переменной. Public/private/protected - синтаксические конструкции, которые проверяются во время компиляции, и они не являются «заразными» или частью типа чего-то.

1

Личный член ничем не отличается от открытого участника или любого другого экземпляра. Итак, да, вы можете взять с ними указатели и вернуть их.

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

Дизайн соображения:

Разоблачение любой из ваших внутренних деталей реализации потенциально является нарушением инкапсуляции. Тем не менее, если вы хотите только инкапсулировать, КАК возвращается или создается объект, который вы возвращаете, это разумное решение. Это позволит вам изменить класс, чтобы получить объект-член каким-либо другим способом (например, запрос файла или внутреннего словаря) без нарушения кода, который вызывает эти методы.

1

«Было бы крушение или есть что-то очень опасное в этом вопросе? Можно ли прочитать или записать точные данные?»

частный/защищенный/общественный не имеет никакого эффекта при времени выполнения, поэтому они не могут влиять на выполнение программы или даже сбой программы. Они проверяются на времени компиляции и просто заставляют ваш компилятор выкидывать ошибку при компиляции, если есть нарушение.

0

Квалификатор const не защитит вас в этих случаях. Учитывая ответ Джеймса, пожалуйста, попробуйте забрасывать const int * к int *

int* cp = (int*)e.get_const(); 

вас будет все еще быть в состоянии изменить.

Смежные вопросы