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

void

Shy::

turn_eyes_down()

{

// ...

_mumble = "excuse me"; // правильно

// правильно: имя члена базового класса квалифицировано

Diffident::_mumble = -1;

}

Функции-члены базового и производного классов не составляют множество перегруженных функций:

class Diffident {

public:

void mumble( int softness );

// ...

};

class Shy : public Diffident {

public:

// скрывает видимость функции-члена Diffident::_mumble,

// а не перегружает ее

void mumble( string whatYaSay );

void print( int soft, string words );

// ...

};

Вызов функции-члена базового класса из производного в этом случае приводит к ошибке компиляции:

Shy simon;

// правильно: Shy::mumble( string )

simon.mumble( "pardon me" );

// ошибка: ожидался первый аргумент типа string

// Diffident::mumble( int ) невидима

simon.mumble( 2 );

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

class Diffident {

public:

void turn_aside( );

// ...

};

class Shy : public Diffident {

public:

// скрывает видимость

// Diffident::turn_aside()

void turn_aside();

// ...

};

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

А если нам действительно нужен набор перегруженных функций-членов базового и производного классов? Написать в производном классе небольшую встроенную заглушку для вызова экземпляра из базового? Это возможно:

class Shy : public Diffident {

public:

// один из способов реализовать множество перегруженных

// членов базового и производного классов

void mumble( string whatYaSay );

void mumble( int softness ) {

Diffident::mumble( softness ); }

// ...

};

Но в стандартном C++ тот же результат достигается посредством using-объявления:

class Shy : public Diffident {

public:

// в стандартном C++ using-объявление

// создает множество перегруженных

// членов базового и производного классов

void mumble( string whatYaSay );

using Diffident::mumble;

// ...

};

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

Обратим внимание на степень доступности защищенных членов базового класса. Когда мы пишем:

class Query {

public:

const vectorlocation* locations() { return &_loc; }

// ...

protected:

vectorlocation _loc;

// ...

};

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

bool

NameQuery::

compare( const Query *pquery )

{

// правильно: защищенный член подобъекта Query

int myMatches = _loc.size();

// ошибка: нет прав доступа к защищенному члену

// независимого объекта Query

int itsMatches = pquery-_loc.size();

return myMatches == itsMatches;

}

У объекта NameQuery есть доступ к защищенным членам только одного объекта Query - подобъекта самого себя. Прямое обращение к ним из производного класса осуществляется через неявный указатель this (см. раздел 13.4). Первая реакция на ошибку компиляции - переписать функцию compare() с использованием открытой функции-члена location():