Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 321 322 [323] 324 325 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#4831
,
|
|
|
|
ааа, блин, невнимательно его код посмотрел =)
|
|
Сообщ.
#4832
,
|
|
|
|
Почему же? Цитата молодец Рихтер Ага. В свое время, если бы не он, системное программирование в windows было бы совсем унылым для меня. Цитата private-метод нельзя так вызвать Он вообще-то protected, так что через super должно быть можно, даже из другого пакета. |
|
Сообщ.
#4833
,
|
|
|
|
а защищенные да, можно перекрыть:
![]() ![]() class Base { protected void f1() { System.out.println("Base.f1()"); } public void f() { f1(); } } class Derived extends Base { protected void f1() { System.out.println("Derived.f1()"); } } public class Test { public static void main(String[] args) { new Derived().f(); } } ![]() ![]() Derived.f1() Добавлено Цитата D_KEY @ Почему же? хз, не нравится мне это направление в сабтайпинге =) |
|
Сообщ.
#4834
,
|
|
|
|
N-арный диспетчер на таблицах "виртуальных" функций почти получился...
Добавлено Ага. Получилось. Исходный текст (без фарша): ![]() ![]() class Base { public: }; class D1 : public Base { public: }; class D2 : public Base { public: }; class D3 : public Base { public: }; void TestDispatch(Base* b1, Base* b2) { std::cout << "Double Base-Base Dispatch" << std::endl; } void TestDispatch(D1* o1, Base* o2) { std::cout << "Double D1-Base Dispatch" << std::endl; } void TestDispatch(D1* o1, D2* o2) { std::cout << "Double D1-D2 Dispatch" << std::endl; } void TestDispatch(D3* o1, D3* o2) { std::cout << "Double D3-D3 Dispatch" << std::endl; } // тут куча шаблонного кода class TestDispatcher { bool m_Reverse; public: TestDispatcher() : m_Reverse(false) {;} template<typename L, typename R> void operator()(L* l, R* r) { TestDispatch(l, r); } template<typename L, typename R> void TestDispatch(L* l, R* r) { if (m_Reverse) ::TestDispatch(l, r); // std::cout << "Default dispatch" << std::endl; else { m_Reverse = true; Dispatcher<TestDispatcher, void, 2, Base*, D1*, D2*, D3*> d; d(this, r, l); } } }; template<typename T> class TestClass { }; int main() { Base b; D1 d1; D2 d2; D3 d3; // TestClass<struct {int a, int b}> t; Dispatcher<TestDispatcher, void, 2, Base*, D1*, D2*, D3*> d; std::cout << "Left is Base" << std::endl; d(&b, &b); d(&b, &d1); d(&b, &d2); d(&b, &d3); std::cout << std::endl << "Left is D1" << std::endl; d(&d1, &b); d(&d1, &d1); d(&d1, &d2); d(&d1, &d3); std::cout << std::endl << "Left is D2" << std::endl; d(&d2, &b); d(&d2, &d1); d(&d2, &d2); d(&d2, &d3); std::cout << std::endl << "Left is D3" << std::endl; d(&d3, &b); d(&d3, &d1); d(&d3, &d2); d(&d3, &d3); return 0; } На выходе имеем: ![]() ![]() Left is Base Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D1 Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D2 Double Base-Base Dispatch Double D1-D2 Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D3 Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double D3-D3 Dispatch Добавлено Ну, точнее, почти получилось. |
|
Сообщ.
#4835
,
|
|
|
|
Во, теперь оно:
![]() ![]() template<typename D> void TestVirtualDisp(D& disp, Base* b1, Base* b2) { disp(b1, b2); } int main() { Base b; D1 d1; D2 d2; D3 d3; // TestClass<struct {int a, int b}> t; Dispatcher<TestDispatcher, void, 2, Base*, D1*, D2*, D3*> d; std::cout << "Left is Base" << std::endl; TestVirtualDisp(d, &b, &b); TestVirtualDisp(d, &b, &d1); TestVirtualDisp(d, &b, &d2); TestVirtualDisp(d, &b, &d3); std::cout << std::endl << "Left is D1" << std::endl; TestVirtualDisp(d, &d1, &b); TestVirtualDisp(d, &d1, &d1); TestVirtualDisp(d, &d1, &d2); TestVirtualDisp(d, &d1, &d3); std::cout << std::endl << "Left is D2" << std::endl; TestVirtualDisp(d, &d2, &b); TestVirtualDisp(d, &d2, &d1); TestVirtualDisp(d, &d2, &d2); TestVirtualDisp(d, &d2, &d3); std::cout << std::endl << "Left is D3" << std::endl; TestVirtualDisp(d, &d3, &b); TestVirtualDisp(d, &d3, &d1); TestVirtualDisp(d, &d3, &d2); TestVirtualDisp(d, &d3, &d3); return 0; } ![]() ![]() Left is Base Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D1 Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D2 Double Base-Base Dispatch Double D1-D2 Dispatch Double Base-Base Dispatch Double Base-Base Dispatch Left is D3 Double Base-Base Dispatch Double D1-Base Dispatch Double Base-Base Dispatch Double D3-D3 Dispatch |
|
Сообщ.
#4836
,
|
|
|
|
Я не этого просил. Я вообще не просил, коль на то пошло. Я говорил о сложности перехода от одной концепции к другой, и в случае использования интерфейсов "по правилам" она выше, ибо требует изменения подхода к реализации. Вот и всё. В случае использования "по уму", т.е. подходя к интерфейсам с позиции абстрактных классов, она может быть (но не обязана, определяется опытом разработчика) ниже. И вообще говоря, наследованием ли, агрегацией ли это будет реализовано, опять же неважно.
То, что изменится поведение и как следствие правила использования получившейся сущности, в общем-то ожидаемо, и тот факт, что это затронет твоего коллегу, совсем не удивительно. Я же использовал этот аргумент исключительно с целью показать наличие факта редизайна, а не просто переброски реализации методов из одного класса в другой, ни на что по факту не влияющей, окромя внутренностей. Вы-таки разберитесь между собой, а. А то один говорит одно, второй говорит прямо противоположное. Чё, прямо тут? А неплюсовики, тусящие тут, за оффтоп не обидятся? Цитата Flex Ferrum @ Ой, думаю, не стоит. RTTI будет разгребать каждый параметр куда как дольше, чем твои имеющиеся мультиметоды дважды сделают виртуальный вызов для него.вполне можно сделать неинтрузивный мультиметод с произвольным числом параметров и константным временем поиска. Правда, получится хит по памяти (многомерная виртуальная таблица),... Это не у меня . Это твои мультиметоды так работают. Компилятор, по очереди проходя по всему typename... или списку типов (которые используют только статические вызовы), инстанцирует каждый акцептор, что даёт линкеру возможность для каждого из них заполнить VMT, независимо от того, используется ли некий тип пользователем в программе или нет. В конце виртуально вызывается акцептор для следующего параметра, что восстанавливает реальный тип этого параметра, и далее всё то же самое повторяется вплоть до финального акцептора, который уже владеет всеми восстановленными типами и вызывает конкретный мультиметод. По факту получается, что финальный акцептор задействует обычные статические мультиметоды, т.е. банальную перегрузку. Честно говоря, не вижу тут неконстантной сложности.Цитата Flex Ferrum @ А что получилось-то? Именно это и было. Ага. Получилось. P.S. Сорри остальным за оффтоп. |
|
Сообщ.
#4837
,
|
|
|
|
scorpion
Цитата scorpion @ О том, что если у тебя нет реализации интерфейса IA, но, он есть в коде, то его полюбасу ктото когдато, попытаеца юзнуть! Бред. Цитата scorpion @ Ок. Пусть будет нельзя. И что получится, если до разделения интерфейса IA, он повсюду используется? Ты, там помница говорил клиент не пострадает? И как он, получается в коде мертвым грузом(IA) будет висеть? Как вы программите? Потом друг друга проклинаете, какого $^%#$%я тут делает половина функциональности, которая не имеет реализации? Так чтоле ? Бред. scorpion KILLER это ты? Ещё раз повторяю, интерфейсы никому не навязывают свою какую-то определённую реализацию, да и средств навязывать, выраженных в декларации, у них нет (а вот у абстрактных классов есть, это и секции доступа и зависимость от частичной реализации). А кто будет следить за временем жизни объекта? Ведь ни объект, ни интерфейсы не знают друг о друге. Подсчет ссылок можно убрать, если нужно. Цитата Qraizer @ и тот факт, что это затронет твоего коллегу, совсем не удивительно. Что ты имеешь ввиду? Цитата Qraizer @ Вы-таки разберитесь между собой, а. А то один говорит одно, второй говорит прямо противоположное. Слушай меня А KILLER тупо троллит (и непробиваемое "и чо?" и намеренное искажение слов собеседника). |
|
Сообщ.
#4838
,
|
|
|
|
Цитата DesweR @ Та причём тут. Вот:Слушай меня А KILLER тупо троллит Цитата Romkin @ Цитата Qraizer @ НАсчет неизвестного инетрфейса ничего не знаю. А вот известный интерфейс от неизвестного объекта вполне нормально получить и заюзать как часть функционала своего объекта.Вон, DesweR рассказывает, как неизвестный при компиляции <T> может быть в run-time получен от неизвестного при компиляции объекта, и тем самым запросто заюзан неизвестный при компиляции интерфейс. Что-то не вяжется. |
|
Сообщ.
#4839
,
|
|
|
|
Цитата Qraizer @ Чё, прямо тут? А неплюсовики, тусящие тут, за оффтоп не обидятся? Ну, давай где-нибудь ещё. ![]() Цитата Qraizer @ Ой, думаю, не стоит. RTTI будет разгребать каждый параметр куда как дольше, чем твои имеющиеся мультиметоды дважды сделают виртуальный вызов для него. Ну, тут вопрос тонкий. Определение типа через RTTI (в случае динамического типа) не сложнее выбора по виртуальной таблице. А дальше, определив типа каждого аргумента, делается простой выбор по многомерному массиву. |
|
Сообщ.
#4840
,
|
|
|
|
Цитата DesweR @ Цитата О том, что если у тебя нет реализации интерфейса IA, но, он есть в коде, то его полюбасу ктото когдато, попытаеца юзнуть! Бред. Можешь обосновать? Или ты мамой просто клянешся? Цитата DesweR @ Цитата Ок. Пусть будет нельзя. И что получится, если до разделения интерфейса IA, он повсюду используется? Ты, там помница говорил клиент не пострадает? И как он, получается в коде мертвым грузом(IA) будет висеть? Как вы программите? Потом друг друга проклинаете, какого $^%#$%я тут делает половина функциональности, которая не имеет реализации? Так чтоле ? Бред. Аналогично, обоснуй. Цитата DesweR @ Слушай меня А KILLER тупо троллит (и непробиваемое "и чо?" и намеренное искажение слов собеседника). Во первых я scorpion, во вторых, слова твои я не искажал. Мне оно не нужно. Можешь показать где я искажал твои слова? |
|
Сообщ.
#4841
,
|
|
|
|
Цитата Flex Ferrum @ В большинстве реализаций (если не во всех) это и будет выборкой по виртуальной таблице.Определение типа через RTTI (в случае динамического типа) не сложнее выбора по виртуальной таблице. Цитата Flex Ferrum @ Поскольку идентификаторы типов скорее всего не будут последовательными числами придется скорее всего задействовать какой-то поиск, что превратит сложность реализации из константной в логарифмическую, или даже линейную, по числу типов. По числу аргументов она и так линейная. А дальше, определив типа каждого аргумента, делается простой выбор по многомерному массиву. |
|
Сообщ.
#4842
,
|
|
|
|
Цитата amk @ Поскольку идентификаторы типов скорее всего не будут последовательными числами придется скорее всего задействовать какой-то поиск, что превратит сложность реализации из константной в логарифмическую, или даже линейную а чем они будут? и чем не устроит хеш-таблица? |
|
Сообщ.
#4843
,
|
|
|
|
Цитата korvin @ Думаю, скорее всего адресами виртуальных таблиц.а чем они будут? Цитата korvin @ Тем, что ее еще нужно будет построить. Коллизиями. чем не устроит хеш-таблица? |
|
Сообщ.
#4844
,
|
|
|
|
Рихтер в силу своей низкоуровневой специфики совсем не понимает смысла инкапсуляции. А смысл инкапсуляции на базе свойств как раз в том, что клиенту и незачем делать предположений по поводу реализации, поле це или метод, и в будущем ты это сможешь изменить не меняя клиентского кода |
|
Сообщ.
#4845
,
|
|
|
|
Цитата --Ins-- @ Рихтер в силу своей низкоуровневой специфики совсем не понимает смысла инкапсуляции. Книга по C#, о какой низкоуровневой специфики идет речь? А самомнение некоторых участников меня таки иногда поражает. Цитата Джеффри Рихтер (англ. Jeffrey Richter) — компьютерный специалист, автор наиболее хорошо продаваемых книг в области Win32 и .NET. Рихтер — соучредитель компании Wintellect, которая обучает ИТ-специалистов и консультирует фирмы в области создания ПО. За годы работы Рихтер консультировал Intel, DreamWorks и Microsoft. Рихтер внёс вклад в следующие проекты: Windows NT 32 и 64, Visual Studio .NET, Microsoft Office, TerraServer, .NET Framework, Windows Vista. Джеффри Рихтер автор колонки S90 в журнале MSDN. Цитата А смысл инкапсуляции на базе свойств Можно подробнее, что именно инкапсулируют свойства? Доступ к полям инкапсулируют соответствующие методы доступа(явно или неявно), а свойства представляют собой синтаксическую надстройку над ними. Или я ошибаюсь? Цитата То, о чем ты говоришь, носит название "принцип унифицированного доступа", который не связан со свойствами(т.е. это особенность синтаксиса и потому это не требует введения новых концепций, таких как "свойства"). Впрочем, korvin уже это пояснял, насколько я помню. как раз в том, что клиенту и незачем делать предположений по поводу реализации, поле це или метод, и в будущем ты это сможешь изменить не меняя клиентского кода |