Выбрать главу

Рассмотрим следующий пример программы.

#include <iostream>

using namespace std;

class base {

 protected:

  int i, j; // Эти члены закрыты в классе base, но доступны для класса derived.

 public:

  void set(int a, int b) { i = a; j = b; }

  void show() { cout << i << " " << j << "\n"; }

};

class derived : public base {

  int k;

 public:

  // Класс derived имеет доступ к членам класса base i и j.

  void setk() { k = i*j; }

  void showk() { cout << k << "\n"; }

};

int main()

{

 derived ob;

 ob.set(2, 3); // OK, классу derived это позволено.

 ob.show(); // OK, классу derived это позволено.

 ob.setk();

 ob.showk();

 return 0;

}

Поскольку класс base унаследован классом derived открытым способом (т.е. как public-класс), и поскольку члены i и j объявлены защищенными в классе base, функция setk() (член класса derived) может получать к ним доступ. Если бы члены i и j были объявлены в классе base закрытыми, то класс derived не мог бы обращаться к ним, и эта программа не скомпилировалась бы.

Узелок на память. Спецификатор protected позволяет создать член класса, который будет доступен в рамках данной иерархии классов, но закрыт для остальных элементов программы.

Если некоторый производный класс используется в качестве базового для другого производного класса, то любой защищенный член исходного базового класса, который наследуется (открытым способом) первым производным классом, может быть унаследован еще раз (в качестве защищенного члена) вторым производным классом. Например, в следующей (вполне корректной) программе класс derived2 имеет законный доступ к членам i и j.

#include <iostream>

using namespace std;

class base {

 protected:

  int i, j;

 public:

  void set(int a, int b) { i = a; j = b; }

  void show() { cout << i << " " << j << "\n"; }

};

// Члены i и j наследуются как protected-члены.

class derived1: public base {

  int k;

 public:

  void setk() { к = i*j; } // правомерный доступ

  void showk() { cout << к << "\n"; }

};

// Члены i и j наследуются косвенно через класс derived1.

class derived2 : public derived1 {

  int m;

 public :

  void setm() { m = i-j; } // правомерный доступ

  void showm() { cout << m << "\n"; }

};

int main()

{

 derived1 ob1;

 derived2 ob2;

 ob1.set (2, 3);

 ob1.show();

 ob1.setk();

 ob1.showk();

 ob2.set (3, 4);

 ob2.show();

 ob2.setk();

 ob2.setm();

 ob2.showk();

 ob2.showm();

 return 0;

}

Если базовый класс наследуется закрытым способом (т.е. с использованием спецификатора private), защищенные (derived) члены этого базового класса становятся закрытыми (private) членами производного класса. Следовательно, если бы в предыдущем примере класс base наследовался закрытым способом, то все его члены стали бы private-членами класса derived1, и в этом случае они не были бы доступны для класса derived2. (Однако члены i и j по-прежнему остаются доступными для класса derived1.) Эта ситуация иллюстрируется в следующей программе, которая поэтому некорректна (и не скомпилируется). Все ошибки отмечены в комментариях.