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

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


class Endangered { public:

ostream& print( ostream& );

...

class Bear : public( ZooAnimal ) { public:

void print( );

using ZooAnimal::feeding time; Time feeding time( int );

...

class Panda : public Bear, public Endangered {

public: ...

int main() {

Panda yin yang;

ошибка: неоднозначность: одна из

Bear::print()

Endangered::print( ostream& )

yin yang.print( cout );

правильно: вызывается Bear::feeding time() yin yang.feeding time( 5 6 );

При поиске объявления функции-члена print() в области видимости класса Panda будут найдены как Bear::print() , так и Endangered::print() . Поскольку они не находятся в одном и том же базовом классе, то даже при разных списках параметров этих функций множество кандидатов оказывается пустым и вызов считается ошибочным. Для исправления ошибки в классе Panda следует определить собственную функцию print() . При поиске объявления функции-члена feeding time() в области видимости Panda будут найдены ZooAnimal::feeding time() и Bear::feeding time() - они расположены в области видимости класса Bear. Так как эти объявления найдены в одном и том же базовом классе, множество кандидатов для данного вызова включает обе функции, а выбирается Bear::feeding time() .

19.3.2. Устоявшие функции и последовательности пользовательских преобразований

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

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



class ZooAnimal { public:

конвертер: ZooAnimal ==> const char* operator const char* ();

...

можем написать следующий конвертер для ZooAnimal:

Производный класс Bear наследует его от своего базового ZooAnimal. Если значение типа Bear используется в контексте, где ожидается const char*, то неявно вызывается

extern void display( const char* ); Bear yogi;

правильно: yogi ==> const char*

конвертер для преобразования Bear в const char*:

display( yogi );

Конструкторы с одним аргументом без ключевого слова explicit образуют другое множество неявных преобразований: из типа параметра в тип своего класса. Определим

class ZooAnimal {

public:

преобразование: int ==> ZooAnimal ZooAnimal( int );

...

такой конструктор для ZooAnimal:

Его можно использовать для приведения значения типа int к типу ZooAnimal. Однако конструкторы не наследуются. Конструктор ZooAnimal нельзя применять для

const int cageNumber = 8788l void mumble( const Bear S ); ошибка: ZooAnimal( int ) не используется

преобразования объекта в случае, когда целевым является тип производного класса:

mumble( cageNumber );

explicit. При наследовании на втором шаге разрешения перегрузки рассматривается более широкое множество таких преобразований.

Конвертеры наследуются, как и любые другие функции-члены класса. Например, мы



extern void release( const ZooAnimal& ); Panda yinYang;

стандартное преобразование: Panda -> ZooAAnimal

имеющихся в классе:

release( yinYang );

Поскольку аргумент yinYang типа Panda инициализирует ссылку на тип базового класса, то преобразование имеет ранг стандартного.

В разделе 15.10 мы говорили, что стандартные преобразования имеют более высокий

public Bear, public Endangered

наследует ZooA\nimal::operator const char *()

class Panda : {

Panda yinYang;

extern void release( const ZooAnimal& ); extern void release( const char * );

стандартное преобразование: Panda -> ZooAnimal выбирается: release( const ZooA\nimal& )

ранг, чем пользовательские:

release( yinYang );

Как release(const char*) , так и release(ZooAnimal&) являются устоявшими функциями: первая потому, что инициализация параметра-ссылки значением аргумента -стандартное преобразование, а вторая потому, что аргумент можно привести к типу

Поскольку целевым типом является Bear - тип параметра функции mumble() , то рассматриваются только его конструкторы.

19.3.3. Наилучшая из устоявших функций

Наследование влияет и на третий шаг разрешения перегрузки - выбор наилучшей из устоявших функций. На этом шаге ранжируются преобразования типов, с помощью которых можно привести фактические аргументы функции к типам соответственных формальных параметров. Следующие неявные преобразования имеют тот же ранг, что и стандартные (стандартные преобразования рассматривались в разделе 9.3):

преобразование аргумента типа производного класса в параметр типа любого из его базовых;

преобразование указателя на тип производного класса в указатель на тип любого из его базовых;

инициализация ссылки на тин базового класса с помощью l-значения тина производного.

Они не являются пользовательскими, так как не зависят от конвертеров и конструкторов,



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

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