MyTetra Share
Делитесь знаниями!
О, смотри-ка какое хорошее место. Дайте два!
Модификаторы public, private и protected в C++
18.07.2015
22:51
Текстовые метки: Модификатор, public, private, protected, C++
Раздел: Компьютер - Программирование - Язык C++

Модификаторы public, private и protected в C++


Public, private и protected — это модификаторы доступа, а не видимости, как ошибочно думают некоторые. Private члены видны снаружи класса, но не доступны.

Теперь кратко, кому какой доступ они предоставляют.

  • Public — доступ открыт всем, кто видит определение данного класса.
  • Private — доступ открыт самому классу (т.е. функциям-членам данного класса) и друзьям (friend) данного класса, как функциям, так и классам.
  • Protected — доступ открыт классам, производным от данного.

Далее приведены примеры доступа с указанием, какие поля в каких местах программы доступны.

class some {

  friend void f(some&);

public:

  int a_;

protected:

  int b_;

private:

  int c_;

};

 

void f(some& obj) {

  obj.a_ = 0; // OK

  obj.b_ = 0; // OK

  obj.c_ = 0; // OK

}

 

void g(some& obj) {

  obj.a_ = 0; // OK

  obj.b_ = 0; // compile time error

  obj.c_ = 0; // compile time error

}

 

class derived : public some {

  derived() {

    a_ = 0; // OK

    b_ = 0; // OK

    c_ = 0; // compile time error

  }

};


В C++ существует public-наследование, private-наследование и protected-наследование. В зависимости от того, какой тип используется, изменяется доступ к членам базового класса для клиентов производного. В таблице сведена информация об этом изменении:



Исходный модификатор доступа

public

private

protected

public-наследование

public

private

protected

private-наследование

private

private

private

protected-наследование

protected

private

protected



Следует добавить, что производный класс может изменить модификатор доступа с protected на public, разместив using объявление в соответствующей секции класса:

class some {

public:

  int a;

protected:

  int b;

private:

  int c;

};

 

class derived : public some {

public:

  using some::b;

};

 

void f(derived& obj) {

  obj.b = 0; // OK

}


Напоследок приведу несколько приёмов, с помощью которых можно «достучаться» до закрытых функций или данных. Допустим, у нас есть класс some и нам нужно обнулить закрытую переменную c:

  • Модифицировать определение класса, добавив друга (функцию или класс)

  • class some {

      friend class some_friend;

    public:

      int a;

    protected:

      int b;

    private:

      int c;

    };

     

    class some_friend {

    public:

      static void hack(some& obj) {

        obj.c = 0;

      }

    };


  • Воспользоваться препроцессором:

  • #define private public

     

    class some {

    public:

      int a;

    protected:

      int b;

    private:

      int c;

    };

     

    void hack(some& obj) {

      obj.c = 0;

    }


  • Создать класс с таким же расположением в памяти и воспользоваться reinterpret_cast для преобразования указателей:

  • class some {

    public:

      int a;

    protected:

      int b;

    private:

      int c;

    };

     

    class hack_some {

    public:

      int a;

      int b;

      int c;

    };

     

    void h(some& obj) {

      reinterpret_cast<hack_some*>(&obj)->c = 0;

    }


  • Если у «взламываемого» класса есть шаблонная функция, можно её специализировать своим типом:

class some {

public:

  int a;

  template<class T> void func(void) {

    a = b + c;

  }

protected:

  int b;

private:

  int c;

};

 

class hack_template_param{};

 

template<>

void some::func<hack_template_param>(void) {

  c = 0;

}

 

void hack(void) {

  some o;

  o.func<hack_template_param>();

};


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

PS: Для компиляторов GCC и CLANG существует опция -fno-access-control, которая позволяет отключить контроль доступа к членам класса со стороны компилятора.


Так же в этом разделе:
← Содержание ...
 
MyTetra Share v.0.35
Яндекс индекс цитирования