Программирование >>  Инициализация объектов класса, структура 

1 ... 334 335 336 [ 337 ] 338 339 340 ... 395


object.memfunc( args );

или функции-члена с помощью операторов доступа точка или стрелка :

pointer->memfunc( args );

В данном разделе мы изучим оба случая.

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

namespace

NS {

class ZooAnimal { /*

void display( const ZooAnimalS );

базов класс Bear объявлен в пространстве имен NS class Bear : public NS::ZooAnimal { };

int main() { Bear baloo;

display( baloo );

return 0; определены базовые классы. Например:

2. Отбор устоявших функций.

3. Выбор наилучшей из устоявших функции.

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

19.3.1. Функции-кандидаты

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

func( args );



namespace NS {

class ZooAnimal {

friend void display( const ZooAnimal& );

базов класс Bear объявлен в пространстве имен NS class Bear : public NS::ZooAnimal { };

int main() { Bear baloo;

display( baloo );

return 0;

предыдущем примере display() объявлена как функция-друг ZooAnimal:

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

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

функций, видим1х в точке вызова;

функций, объявленных в тех пространствах имен, где определен тин класса или любой из его базовых;

функций, являющихся друзьями этого класса или любого из его базовых.

Наследование влияет также на построение множества кандидатов для вызова функции-члена с помощью операторов точка или стрелка . В разделе 18.4 мы говорили, что объявление функции-члена в производном классе не перегружает, а скрывает одноименные функции-члены в базовом, даже если их списки параметров различны:

Аргумент baloo имеет тин класса Bear. Кандидатами для вызова display() будут не только функции, объявления которых видимы в точке ее вызова, но также и те, что объявлены в пространствах имен, в которых объявлены класс Bear и его базовый класс ZooAnimial. Поэтому в множество кандидатов добавляется функция display(const ZooAnimial&), объявленная в пространстве имен NS.

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



class ZooAnimal { public:

Time feeding time( string );

...

class Bear : public ZooAnimal { public:

скрает ZooAnimal::feeding time( string ) Time feeding time( int );

...

Bear Winnie;

ошибка: ZooAnimal::feeding time( string ) скрыта Winnie.feeding time( Winnie );

Функция-член feeding time(int), объявленная в классе Bear, скрывает feeding time(string) , объявленную в ZooAnimal, базовом для Bear. Поскольку функция-член вызывается через объект Winnie типа Bear, то при поиске кандидатов для этого вызова просматривается только область видимости класса Bear, и единственным кандидатом будет feeding time(int). Так как других кандидатов нет, вызов считается ошибочным.

Чтобы исправить ситуацию и заставить компилятор считать одноименные функции-члены базового и производного классов перегруженными, разработчик производного класса может ввести функции-члены базового класса в область видимости производного

class Bear : public ZooAnimal { public:

feeding time( int ) перегружает экземпляр из класса ZooAnimal using ZooAnimal::feeding time; Time feeding time( int );

...

с помощью using-объявлений:

Теперь обе функции feeding time() находятся в области видимости класса Bear и,

правильно: вызается ZooAnimal::feeding time( string )

следовательно, войдут в множество кандидатов:

Winnie.feeding time( Winnie );

В такой ситуации вызывается функция-член feeding time( string ) .

В случае множественного наследования при формировании совокупности кандидатов объявления функций-членов должны быть найдены в одном и том же базовом классе, иначе вызов считается ошибочным. Например:



1 ... 334 335 336 [ 337 ] 338 339 340 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика