будет компилироваться, так как next – открытый член и employee и manager'а. Альтернатива – можно определить закртый (private) класс, просто опустив в описании класса слово public:

class manager : employee (* // ... *);

Это означает, что открытый член класса employee является закрытым членом класса manager. То есть, функции члены класса manager могут как и раньше использовать открытые члены класса employee, но для пользователей класса manager эти члены ндоступны. В частности, при таком описании класса manager функция clear компилироваться не будет. Друзья производного класса имеют к членам базового класса такой же доступ, как и функции члены.

Поскольку, как оказывается, описание открытых базовых классов встречается чаще описания закрытых, жалко, что описние открытого базового класса длиннее описания закрытого. Это, кроме того, служит источником запутывающих ошибок у нчинающих.

Когда описывается производная struct, ее базовый класс по умолчанию является public базовым классом. То есть,

struct D : B (* ...

означает

class D : public B (* public: ...

Отсюда следует, что если вы не сочли полезным то сокртие данных, которое дают class, public и friend, вы можете просто не использовать эти ключевые слова и придерживаться struct. Такие средства языка, как функции члены, конструкторы и перегрузка операций, не зависят от механизма сокрытия даных.

Можно также объявить некоторые, но не все, открытые члны базового класса открытыми членами производного класса. Например:

class manager : employee (* // ... public: // ... employee::name; employee::department; *);

Запись

имя_класса :: имя_члена ;

не вводит новый член, а просто делает открытый член бзового класса открытым для производного класса. Теперь name и department могут использоваться для manager'а, а salary и age – нет. Естественно, сделать закрытый член базового класса окрытым членом производного класса невозможно. Невозможно с помощью этой записи также сделать открытыми перегруженные имена.

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

<p>7.2.4 Указатели</p>

Если производный класс derived имеет открытый базовый класс base, то указатель на derived можно присваивать перменной типа указатель на base не используя явное преобразовние типа. Обратное преобразование, указателя на base в указтель на derived, должно быть явным. Например:

class base (* /* ... */ *); class derived : public base (* /* ... */ *);

derived m; base* pb = amp;m; // неявное преобразование derived* pd = pb; // ошибка: base* не является derived* pd = (derived*)pb; // явное преобразование

Иначе говоря, объект производного класса при работе с ним через указатель и можно рассматривать как объект его бзового класса. Обратное неверно.

Будь base закрытым базовым классом класса derived, неяное преобразование derived* в base* не делалось бы. Неявное преобразование не может в этом случае быть выполнено, потому что к открытому члену класса base можно обращаться через укзатель на base, но нельзя через указатель на derived:

class base (* int m1; public: int m2; // m2 – открытый член base *);

class derived : base (* // m2 – НЕ открытый член derived *);

derived d; d.m2 = 2; // ошибка: m2 из закрытой части класса base* pb = amp;d; // ошибка: (закрытый base) pb-»m2 = 2; // ok pb = (base*) amp;d; // ok: явное преобразование pb-»m2 = 2; // ok

Помимо всего прочего, этот пример показывает, что ипользуя явное приведение к типу можно сломать правила защиты. Ясно, делать это не рекомендуется, и это приносит программиту заслуженную «награду». К несчастью , недисциплинированное использование явного преобразования может создать адские уловия для невинных жертв, эксплуатирующих программу, в котрой это делается. Но, к счастью, нет способа воспользоваться приведением для получения доступа к закрытому имени m1. Зарытый член класса может использоваться только членами и друзьями этого класса.

<p>7.2.5 Иерархия типов</p>

Производный класс сам может быть базовым классом. Например:

class employee (* ... *); class secretary : employee (* ... *); class manager : employee (* ... *); class temporary : employee (* ... *); class consultant : temporary (* ... *); class director : manager (* ... *); class vice_president : manager (* ... *); class president : vice_president (* ... *);

Такое множество родственных классов принято называть ирархией классов. Поскольку можно выводить класс только из оного базового класса, такая иерархия является деревом и не может быть графом более общей структуры. Например:

class temporary (* ... *); class employee { ... *); class secretary : employee (* ... *);

// не С++: class temporary_secretary : temporary : secretary(* ... *); class consultant : temporary : employee (* ... *);

Перейти на страницу:

Похожие книги