|
Программирование >> Полиморфизм без виртуальных функций в с++
в таком случае А: :handle () - корректная конструкция С++, хотя, возможно, и неправильная. Использование inherited: : handle {) здесь неоднозначно и вызывает ошибку во время компиляции. Я думою, что такое поведение желательно, ибо заставляет пользователя, объединяющего иерархии, явно разрешать неоднозначность. С другой стороны, донный пример показывает, что при использовании множественного носледовония полезность ключевого слово inherited: : ограничена . Меня убедили эти доводы, к тому же сопроводительная документация была тшательно продумана. Таким образом, предложение полезно, нетрудно для понимания и реализации. Имелся и опыт применения, поскольку некий подобный вариант был реализован компанией Apple на основе экспериментов с Object Pascal, а кроме того, это не что иное, как вариация на тему слова super в Smalltalk. Но вслед за последним обсуждением предложения в комитете Дэг сам посоветовал включить это в книгу как хрестоматийный пример хорошей, но непринятой идеи [Stroustrup, 1992b]: Предложение хорошо оргументировоно... В донном случае его реализовывал представитель от компании Apple. При обсуждении мы быстро пришли к выводу, что серьезных изъянов нет. В отличие от более ранних предложений на ту же тему (некоторые из которых восходили еще к временам споров по поводу множественного наследования в 1986 г.) оно корректно разрешало неоднозначности при использовании множественного наследования. Мы согласились, что реализовать расширение будет просто, о программистом оно будет весьма полезно. Заметим, что всего этого еще недостаточно, чтобы одобрить предложение. Ном известно несколько десятков мелких усовершенствований вроде этого и, по крайней мере, дюжина крупных. Если бы мы приняли их все, то язык утонул бы из-за собственной тяжести (вспомним коробль Vasa !). Однако в какой-то момент обсуждения вошел Майкл Тимон, бормоча себе под нос что-то вроде но ном такое расширение ни к чему; мы и без него умеем это делать . Когда утихли возгласы до нет же! , Майкл продемонстрировал нам следующее: class foreman : public employee { typedef employee inherited; ... void print{); class manager : public foreman { typedef foreman inherited; ... void print(); void manager::print{) { inherited::print{); . . . Дальнейшее обсуждение данного примера можно найти в [2nd, стр. 205]. Мы не заметили, что восстановление в С++ вложенных классов открыло возможность управления областью действия и разрешением имен типов точно ток же, кок и любых других имен. Увидев, что такой прием есть, мы решили направить усилия но роботу над каким-нибудь другим аспектом стандарта. Преимущества inherited: : как встроенного средства не пере-вешиволи того факто, что программист и так мог использовать определенное ключевое слово для обозначения базового классе, применяя уже имеющиеся возможности. Поэтому было решено не принимать расширение inherited: : . 13.7. Ослабление правил замещения Рассмотрим, как можно написать функцию, возвращающую копию объекта. Если имеется копирующий конструктор, то это тривиально: class В { public: virtual В* cloneO { return new B{*this); } ... Теперь можно клонировать объект любого класса, производного от В, если в не.м замещена функция В: : clone. Например: class D : public В { public: старое правило: cloneO должна возвращать В*, если хочет заместить В::с1опе{) В* cloneO { return new D(*this); } void h 0; . . . void f(B* pb, D* pd) { B* pbl = pb->clone{); B* pb2 = pd->clone{); pb2 указывает на D ... Увы, знание о том, что pd указывает на D (или на объект какого-то класса, производного от D), утрачено: void g{D* pd) { В* pbl = pd->clone{); правильно D* pdl = pd->clone{); ошибка: cloneO возвращает В* pd->cloneO->h{); ошибка: clone О возвращает В* неудачный обходной путь D* pd2 = (D*)pd->cloneO ; ((D*)pd->clone())->h(); void gg(3* pb, D* pd) { B* pbl = pd->clone(); правильно D* pdl = pd->clone{); правильно pd->clone()->h(); правильно D* pd2 = pb->clone{); ошибка (как и раньше) pb->clone()->h(); ошибка (как и раньше) Это расширение - предложил Алан Снайдер (Alan Snyder) - стало первы.м официально представленны.м на paccMorpeinie комитета и было принято в 1992 г Но прежде че.м одобрить его, следовало ответить на два вопроса: □ не вызовет ли расширение каких-либо серьезных проблем в реализации (скажем, связанных с .мпожестве1шым наследованием или указателя.ми на члены)? □ какие 11реобразова1П1Я, которые можно было бы применить к типу значения, возвращаемого замещающей функцией, стоит рассматривать? Первый вопрос меня не очень волновал: я ду.мал, что знаю, как реализовать ослабление правил в стандартном случае. Однако Мартина ОРиордана это беспокоило, поэтому он представил комитету детальное письметгае обоснование возможности реализации. Трудней всего было решить, стоит ли вообше зани.маться ослаблением и для каких именно преобразований. Часто ли возникает необходи.мость вызывать виртуальные функции для объекта производного тина и выполнять операции над воз-вращаемы.м значением, имеющим этот тип? Несколько человек, в особенности Джон Бранс (John Bruns) и Билл Гиббоне, уверенно доказывали, что такая необходимость возникает постоянно, а не только в при.мерах из теории ко.мпиляторов, вроде clone. В конце концов .меня убедило сделанное Тедом Голдстейно.м (Ted Goldstein) наблюдение, что почти две трети всех приведений типов в программе из 100 тыс. строк, над которой он работал в Sun, были нужны только для того, чтобы обойти труд1юсти, ие возникпте бы при ослаблении правила за-мещения. Другим слова.ми, ослабление позволяет продолжать важную работу, оставаясь в рамках системы типов и пе прибегая к приведе1Н1я.м. Итак, ослаблешш правила Оказалось, в реальных программах это мешает. Также было отмечено, что правило, соглас1го которому замещающая функция долж1ш и.меть в точности тот же тип, что и замещаемая, можно ослабить, не нарушая систему типов и не усложняя реализацию. Напри.мер, можно было бы разрешить такое: class D : public В { public: заметим, clone{) возвращает D* D* clone{) { return new D{*this); } void h{); . . .
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |