привели бы к ошибке повторного определения, так как их сигнатуры одинаковы. Однако запись правильна, поскольку каждая функция находится в области видимости того класса, в котором определена.
А если нам действительно нужен набор перегруженных функций-членов базового и производного классов? Написать в производном классе небольшую встроенную заглушку для вызова экземпляра из базового? Это возможно:
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():
bool
NameQuery::
compare( const Query *pquery )
{
// правильно: защищенный член подобъекта Query
int myMatches = _loc.size();
// правильно: используется открытый метод доступа
int itsMatches = pquery-locations()-size();
return myMatches == itsMatches;
}
Однако проблема заключается в неправильном проектировании. Поскольку _loc - это член базового класса Query, то место compare() среди членов базового, а не производного класса. Во многих случаях подобные проблемы могут быть решены путем переноса некоторой операции в тот класс, где находится недоступный член, как в приведенном примере.
Этот вид ограничения доступа не распространяется на доступ изнутри класса к другим объектам того же класса:
bool
NameQuery::
compare( const NameQuery *pname )
{
int myMatches = _loc.size(); // правильно
int itsMatches = name-_loc.size(); // тоже правильно
return myMatches == itsMatches;
}
Производный класс может напрямую обращаться к защищенным членам базового в других объектах того же класса, что и он сам, равно как и к защищенным и закрытым членам других объектов своего класса.