Лекции.ИНФО


После ознакомления с общей процедурой наследования одним классом другого можно перейти и к деталям этой темы.



Управление доступом к членам базового класса

Если один класс наследует другой, члены базового класса становятся членами производного. Статус доступа членов базового класса в производном классе определяется спецификатором доступа, используемым для наследования базового класса. Спецификатор доступа базового класса выражается одним из ключевых слов: public, private или protected. Если спецификатор доступа не указан, то по умолчанию используется спецификатор private, если речь идет о наследовании типа class. Если же наследуется тип struct, то при отсутствии явно заданного спецификатора доступа по умолчанию используется спецификатор public. Рассмотрим рамификацию (разветвление) использования спецификаторов public или private. (Спецификатор protected описан в следующем разделе.)

Если базовый класс наследуется как public-класс, его public-члены становятся public-членами производного класса.

Если базовый класс наследуется как publie-класс, все его public-члены становятся public-членами производного класса. Во всех случаях private-члены базового класса остаются закрытыми в рамках этого класса и не доступны для членов производного. Например, в следующей программе public-члены класса base становятся public-членами класса derived. Следовательно, они будут доступны и для других частей программы.

#include <iostream>

using namespace std;

class base {

  int i, j;

 public:

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

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

};

class derived : public base {

  int k;

 public:

  derived(int x) { k = x; }

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

};

Int main()

{

 derived ob(3);

 ob.set(1, 2); // доступ к членам класса base

 ob.show(); // доступ к членам класса base

 ob.showk(); // доступ к члену класса derived

 return 0;

}

Поскольку функции set() и show() (члены класса base) унаследованы классом derived как public-члены, их можно вызывать для объекта типа derived в функции main(). Поскольку члены данных i и j определены как private-члены, они остаются закрытыми в рамках своего класса base.

Если базовый класс наследуется как private-класс, его public-члены становятся private-членами производного класса.

Противоположностью открытому (public) наследованию является закрытое (private). Если базовый класс наследуется как private-класс, все его public-члены становятся private-членами производного класса. Например, следующая программа не скомпилируется, поскольку обе функции set() и show() теперь стали private-членами класса derived, и поэтому их нельзя вызывать из функции main().

// Эта программа не скомпилируется.

#include <iostream>

using namespace std;

class base {

  int i, j;

 public:

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

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

};

// Открытые члены класса base теперь становятся

// закрытыми членами класса derived.

class derived : private base {

  int k;

 public:

  derived(int x) { k = x; }

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

};

Int main()

{

 derived ob (3);

 ob.set(1, 2); // Ошибка, доступа к функции set() нет.

 ob.show(); // Ошибка, доступа к функции show() нет.

 return 0;

}

Важно запомнить, что в случае, если базовый класс наследуется как private-класс, его открытые члены становятся закрытыми (private) членами производного класса. Это означает, что они доступны для членов производного класса, но не доступны для других частей программы.

Использование защищенных членов

Член класса может быть объявлен не только открытым (public) или закрытым (private), но и защищенным (protected). Кроме того, базовый класс в целом может быть унаследован с использованием спецификатора protected. Ключевое слово protected добавлено в C++ для предоставления механизму наследования большей гибкости.

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

Спецификатор доступа protected объявляет защищенные члены или обеспечивает наследование защищенного класса.

Как вы знаете, закрытый член базового класса не доступен никаким другим частям программы, включая и производные классы. Однако с защищенными членами все обстоит иначе. Если базовый класс наследуется как public-класс, защищенные члены базового класса становятся защищенными членами производного класса, т.е. доступными для производного класса. Следовательно, используя спецификатор protected, можно создать члены класса, которые закрыты в рамках своего класса, но которые может унаследовать производный класс, причем с получением доступа к ним.

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

#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 << ""; }

};

class derived : public base {

  int k;

 public:

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

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

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

};

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 << ""; }

};

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

class derived1: public base {

  int k;

 public:

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

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

};

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

class derived2 : public derived1 {

  int m;

 public :

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

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

};

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.) Эта ситуация иллюстрируется в следующей программе, которая поэтому некорректна (и не скомпилируется). Все ошибки отмечены в комментариях.

// Эта программа не скомпилируется.

#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 << ""; }

};

// Теперь все элементы класса base будут закрыты

// в рамках класса derived1.

class derived1 : private base {

  int k;

 public:

  // Вызовы этих функций вполне законны, поскольку

  // переменные i и j являются одновременно

  // private-членами класса derived1.

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

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

};

// Доступ к членам i, j, set() и show() не наследуется.

class derived2 : public derived1 {

  int m;

 public :

  // Неверно, поскольку члены i и j закрыты в рамках

  // класса derived1.

  void setm() { m = i-j; } // ошибка

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

};

Int main()

{

 derived1 ob1;

 derived2 ob2;

 ob1.set(1, 2); // Ошибка: нельзя вызывать функцию set().

 ob1.show(); // Ошибка: нельзя вызывать функцию show().

 ob2.set(3, 4); // Ошибка: нельзя вызывать функцию set().

 ob2.show(); // Ошибка: нельзя вызывать функцию show().

 return 0;

}

Несмотря на то что класс base наследуется классом derived1 закрытым способом, класс derived1, тем не менее, имеет доступ к public- и protected-членам класса base. Однако он не может эту привилегию передать дальше, т.е. вниз по иерархии классов. Ключевое слово protected— это часть языка C++. Оно обеспечивает механизм защиты определенных элементов класса от модификации функциями, которые не являются членами этого класса, но позволяет передавать их "по наследству".

Спецификатор protected можно также использовать в отношении структур. Но его нельзя применять к объединениям, поскольку объединение не наследуется другим классом. (Некоторые компиляторы допускают использование спецификатора protected в объявлении объединения, но, поскольку объединения не могут участвовать в наследовании, в этом контексте ключевое слово protected будет равносильным ключевому слову private.)

Спецификатор защищенного доступа может стоять в любом месте объявления класса, но, как правило, protected-члены объявляются после (объявляемых по умолчанию) private-членов и перед public-членами. Таким образом, самый общий формат объявления класса обычно выглядит так.

class имя_класса {

  private-члены

 protected:

  protected-члены

 public:

  public-члены

};









Читайте также:

  1. I. Наименование создаваемого общества с ограниченной ответственностью и его последующая защита
  2. II. Вычленение первого и последнего звука из слова
  3. III. Соблазн и его непосредственные последствия
  4. IV. Падение отработочной системы.
  5. IV. Причины и экономические последствия Великих географических открытий
  6. SWOT-анализ: характеристики при оценке сильных и слабых сторон компании, ее возможностей и угроз ей
  7. VII. Последний вопрос, всё еще остающийся без ответа
  8. VIII. Настройка одним касанием
  9. VIII. НАСТРОЙКА ОДНИМ КАСАНИЕМ
  10. А можно ли сказать, что Природа есть нечто определенное?
  11. А. ИЗ ВЫСТУПЛЕНИЯ Н. С. ХРУЩЕВА В ОБЩЕЙ ДИСКУССИИ НА XV СЕССИИ ГЕНЕРАЛЬНОЙ АССАМБЛЕИ ОРГАНИЗАЦИИ ОБЪЕДИНЕННЫХ НАЦИЙ. 23 СЕНТЯБРЯ 1960 г.
  12. А. Можно разделить и молекулу, и атом. Б. Можно разделить молекулу, невозможно разделить атом. В. Можно разделить атом, невозможно разделить молекулу. Г. Невозможно разделить ни молекулу, ни атом.


Последнее изменение этой страницы: 2016-03-17; Просмотров: 100;


lektsia.info 2017 год. Все права принадлежат их авторам! Главная