
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.7] |
![]() |
|
Страницы: (117) « Первая ... 102 103 [104] 105 106 ... 116 117 ( Перейти к последнему сообщению ) |
![]() |
Сообщ.
#1546
,
|
|
Цитата Flex Ferrum @ - Методы, которые обязаны быть перегружены, не имеют дефолтной реализации, и не могут быть вызваны из производных классов; наследник имеет доступ к private-секции предка? ![]() а абстрактный метод в private-секции - это вообще ересь (в Delphi) |
Сообщ.
#1547
,
|
|
|
А к чему тут вообще крики о каких-то канонах ООП или достоинствах/недостатках Дельфи/С++, когда промышленость - это всего лишь стадо обезьян?
Цитата Shaggy @ наследник имеет доступ к private-секции предка? ![]() Виртуальность определяется лишь сигнатурой. Расположение относительно спецификатора доступа(public/protected/private) не имеет значения при вызове реализации. Спецификатор доступа имеет значение лишь при разрешении имён(какую ф-цию вызываем), а дальнейший механизм "поиска" конкретной реализации(по VMT) не в курсе о том, в какой секции эта реализация расположена и доступна ли эта секция из точки вызова. В Дельфи всё устроено точно также, только, возможно, компилятор запрещает перекрывать закрытые виртуальные метода. |
![]() |
Сообщ.
#1548
,
|
|
Цитата b-a1 @ А к чему тут вообще крики о каких-то канонах ООП или достоинствах/недостатках Дельфи/С++, когда промышленость - это всего лишь стадо обезьян? К тому, что этих обезьян нужно как-то приспособить для создания более-менее вменяемого кода. Широкие возможности для совершения ошибок в руках обезьян подобные усилия сводят на нет. |
Сообщ.
#1549
,
|
|
|
b-a1
Цитата Вспоминаем основы разделения доступа в Delphi . Public доступен всем кому угодно. Protected доступен в любом модуле, в котором ты наследуешься от данного класса. Private доступен в модуле, в котором присутствует объявление данного класса. В итоге, делая forward declaration нужного класса(да, с синтаксисом я немного ошибся), мы получаем доступ в private/protected нужного класса на весь модуль целиком. Разве нет? Ты кое что не учел ![]() Ты, как ветеран данного холивара (должен хорошо разбираться в теме), лучше расскажи мне другое ![]() ![]() ![]() Добавлено Цитата Дык вот, повторю измусоленную фразу "в самой возможности ничего странного нет". Сама возможность нарушить принцип инкапсуляции, скажем, сводит этот принцип на нет ![]() Добавлено Flex Ferrum Ваши третий и четвертый пункт, о которых вы говорите, и выдаете их за "сверхгибкий" механизм, на самом деле является именно рюшечкой. Так как не должно быть такого в грамотно спроектированной системе. Нельзя заставить собаку реветь, но если возникает такая необходимость - то стоит пересмотреть архитектуру. Хотя никто в C++ этим, разумеется, заниматься не будет, бо язык позволяет это обойти. Вы посмотрите на это не со стороны возможностей C++, а со стороны ограничений ООП ![]() |
Сообщ.
#1550
,
|
|
|
Цитата --Ins-- @ Ты кое что не учел private позволяет получить доступ к члену класса в пределах именно модуля, а не класса, это документированное поведение. Тут судя по всему наложилась идеология языка Pascal. Угу. И решена эта проблема не очень давно. И, к сожалению, такой доступ и до сих пор используется в VCL ![]() На самом деле, это было сделано изначально для совместимости с TP7. Но из другого модуля получить доступ к private, насколько я знаю, нельзя иначе как грубым хаком. |
![]() |
Сообщ.
#1551
,
|
|
Цитата --Ins-- @ Сама возможность нарушить принцип инкапсуляции, скажем, сводит этот принцип на нет ![]() Я бы не был так категоричен. Так же как рефлексия не может нарушать инкапсуляции каких-либо классов лишь благодаря своему существованию, так и данные особенности C++ не обязывают никого их эксплуатировать. Меня вполне устраивает следующий довод: То есть C++ не является объектно-ориентированным языком; он предоставляет возможность писать объектно-ориентированный код, а это две большие разницы. И для человека, знающего C++, нет ничего противоестественного в существовании некоторых значимых нюансов, неразличимых для прочих. Просто это другой язык, язык, который нужно хорошо знать, чтобы писать что-то вменяемое ![]() |
Сообщ.
#1552
,
|
|
|
Цитата Угу. И решена эта проблема не очень давно. 5-6 лет как, если не ошибаюсь. Вроде с Delphi 8. Цитата Но из другого модуля получить доступ к private, насколько я знаю, нельзя иначе как грубым хаком. Счиатай, что никак нельзя, так как в другой версии класса этот код может перестать работать. wind Возможно. Вот только взгляд на ООП в C++ по меньшей мере странный, как мне кажется. Правильно Romkin однажды заметил, что перейти с C++ на какой-либо другой язык будет сложно, не поймешь идеологию, в которой слишком много ограничений ![]() |
Сообщ.
#1553
,
|
|
|
Цитата --Ins-- @ Ваши третий и четвертый пункт, о которых вы говорите, и выдаете их за "сверхгибкий" механизм, на самом деле является именно рюшечкой. Так как не должно быть такого в грамотно спроектированной системе. Нельзя заставить собаку реветь, но если возникает такая необходимость - то стоит пересмотреть архитектуру. Хотя никто в C++ этим, разумеется, заниматься не будет, бо язык позволяет это обойти. Вы посмотрите на это не со стороны возможностей C++, а со стороны ограничений ООП ![]() Видимо, ты не совсем понял - о чем идет речь. Если предоставление дефолтной реализации некоего виртуального метода нарушает какие-то фундаментальные принципы ООП - то какие? Проектировщик класса свободен в своем выборе - как и каким образом ему проектировать интерфейс и контракты. Чем это нарушает принципы ООП? |
Сообщ.
#1554
,
|
|
|
Цитата Если предоставление дефолтной реализации некоего виртуального метода нарушает какие-то фундаментальные принципы ООП - то какие? Те, что виртуальные методы по определению являются методами позднего связывания. Если нужно использовать базовую реализацию в классе-потомке, заведи у базового класса статический метод. Хотя я, если честно, не могу представить ситуацию, где такое (именно вызов виртуального метода как статического) может потребоваться и быть оправдано. Цитата Проектировщик класса свободен в своем выборе Вот в этом и вся соль. Вы называете это свободой, а я - вседозволенностью. Вы смотрите на нее с положительной стороны, а я - с отрицательной. Добавлено Цитата Хотя я, если честно, не могу представить ситуацию, где такое (именно вызов виртуального метода как статического) может потребоваться и быть оправдано. Если не возражаете - еще один пример из своей недавней практики. У меня был базовый класс TPalette - некая палитра. У него была куча потомков - TRGBPalette, THLSPalette, TLABPalette. У базового класса был объявлен виртуальный метод Default, который сбрасывал палитру в состояние по умолчанию. Его реализация: TPalette - устанавливает равномерную ч/б палитру TRGBPalette - устанавливает равномерную ч/б палитру THLSPalette - устанавливает равномерную радужную палитру TLABPalette - градиентный переход от оранжевого через белый к голубому. В потомках класса TPalette часто приходилось также устанавливать черно-белую палитру. В C++ вы бы наверняка для этого вызывали виртуальный Default как статический для класса TPalette. Так? Недостаток такого подхода в том, что клиентский код должен знать об аспектах реализации базового класса. Это не есть гуд, так как в идеале базовый класс должен только предоставлять интерфейс клиенту, его реализация клиента не волнует. Я поступил иначе - завел у TPalette публичный метод GrayScale, а реализация TPalette.Default просто его вызывала. В результате я получил тот же самый эффект, только клиенту кроме интерфейса о базовом классе ничего знать не нужно. И нет никаких грязных вызовов виртуальных методов как статических. |
Сообщ.
#1555
,
|
|
|
Цитата --Ins-- @ Те, что виртуальные методы по определению являются методами позднего связывания. Если нужно использовать базовую реализацию в классе-потомке, заведи у базового класса статический метод. Хотя я, если честно, не могу представить ситуацию, где такое (именно вызов виртуального метода как статического) может потребоваться и быть оправдано. Ты до сих пор не понимаешь о чем я говорю. Простой пример: ![]() ![]() class Base { public: void foo() {FooImpl();} void bar() {BarImpl();} protected: void FooImpl() {std::cout << "Base::FooImpl" << std::endl;} void BarImpl() {std::cout << "Base::BarImpl" << std::endl;} }; class Derived : publiс Base { protected: void FooImpl() {Base::FooImpl(); std::cout << "Derived::FooImpl" << std::endl;} }; //... Base b1; Derived d1; Base* b2 = &d1; b2->foo(); // На экран выведется Base::FooImpl Derived::FooImpl b2->bar(); // На экран выведется Base::BarImpl //... Чем этот код нарушает принципы ООП? Добавлено Или для тебя не понятна разница между контрактом с клиентом и контрактом с наследником? И чем отличаются спецификаторы public и protected? |
Сообщ.
#1556
,
|
|
|
Цитата Чем этот код нарушает принципы ООП? Именно этот - ничем. Здесь все нормально, через ссылку b2 методы вызываются именно как виртуальные. А вызов унаследованной реализации в перекрытой - это нормально. Об этом уже речь была несколько страниц назад. Добавлено Цитата Или для тебя не понятна разница между контрактом с клиентом и контрактом с наследником? И чем отличаются спецификаторы public и protected? Понятно, я понял теперь о чем вы. В приведенном коде - все в порядке. |
Сообщ.
#1557
,
|
|
|
Цитата --Ins-- @ Понятно, я понял теперь о чем вы. В приведенном коде - все в порядке. Так вот я и спрашиваю - могу ли я подобные фишки проворачивать в Delphi? ![]() |
Сообщ.
#1558
,
|
|
|
Цитата могу ли я подобные фишки проворачивать в Delphi? Да. Директива inherited используется в реализации классов-потомков, позволяя вызывать из них реализацию предка, дабы не дублировать код: ![]() ![]() TDerived = class(TBase); public procedure FooImpl; override; end; ... procedure TDerived.FooImpl; begin inherited FooImpl; Writeln('Derived.FooImpl'); end; В клиентском же коде возможность использования директивы inherited языком не предусмотрена. |
Сообщ.
#1559
,
|
|
|
А если я хочу с одной стороны - потребовать обязательной перегрузки метода в потомке, с другой - предложить этому потому дефолтную реализацию этого метода. Что мне делать?
|
Сообщ.
#1560
,
|
|
|
Цитата Flex Ferrum @ Так вот я и спрашиваю - могу ли я подобные фишки проворачивать в Delphi? Насколько я понял, в приведенном коде функции не виртуальные? Это специально? И в С++ идет привязка по именам? |