Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 338 339 [340] 341 342 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#5086
,
|
|
|
|
korvin, мне помнится, что ты был за то, чтобы не делать в рантайме то, что можно сделать во время компиляции
Или я ошибаюсь? |
|
Сообщ.
#5087
,
|
|
|
|
или даже так:
![]() ![]() class Impl<T> { public void f() { System.out.println("Default"); } } class A<T> { private Impl<T> impl; public A(Impl<T> impl) { this.impl = impl; } public void use() { impl.f(); } } class Some {} class SomeImpl<T extends Some> extends Impl<T> { public void f() { System.out.println("Some"); } } class Other extends Some {} class Another extends Some {} class AnotherImpl<T extends Another> extends Impl<T> { public void f() { System.out.println("Another"); } } public class Main { public static void main(String[] args) { A<String> stringA = new A<>(new Impl<String>()); A<Some> someA = new A<>(new SomeImpl<Some>()); A<Other> otherA = new A<>(new SomeImpl<Other>()); A<Another> anotherA = new A<>(new AnotherImpl<Another>()); stringA.use(); someA.use(); otherA.use(); anotherA.use(); } } ![]() ![]() Default Some Some Another Добавлено Цитата D_KEY @ korvin, мне помнится, что ты был за то, чтобы не делать в рантайме то, что можно сделать во время компиляции Или я ошибаюсь? мне помнится, мы тут не этапы обсуждаем |
|
Сообщ.
#5088
,
|
|
|
|
Цитата korvin @ мне помнится, мы тут не этапы обсуждаем А что же? Есть полиморфизм статический, есть динамический. В одном случае тебе будет удобнее одно, в другом - другое. Причем они друг другу не мешает и умение их правильно сочетать является одним из главных скиллов для С++ программиста. И тут дело даже не в кодировании, а в проектировании. Шаблоны позволяют тебе гибко создавать нужные типы. Вот в твоем коде все построено на композиции объектов, в С++ном же коде будут созданы соответствующие типы. Полистай первую(вроде бы) главу "Современного проектирования на С++"(книга немного устарела, но для нашего обсуждения это не важно), там где идет речь именно о проектировании с использованием политик(стратегий) и характеристик. |
|
Сообщ.
#5089
,
|
|
|
|
Цитата D_KEY @ А что же? все остальные особенности, свойства параметров, специализацию вот сейчас обсуждаем. |
|
Сообщ.
#5090
,
|
|
|
|
korvin, а с этим как быть:
![]() ![]() template<typename T> class A { public: void f() { data.f(); } void g() { data.g(); } private: T data; }; struct MyStruct { // ... void f(); // ... // void g() - нет }; //... A<MyStruct> obj; // Ok // пока мы не попытаемся вызвать obj.g(), // ошибки не будет и нам будет доступно все остальное из A<MyStruct>. // Как только мы попытаемся воспользоваться obj.g() мы получим ошибку компиляции. Такое поведение связано именно с тем, что мы работает во время компиляции и манипулируем типами, а не объектами. |
|
Сообщ.
#5091
,
|
|
|
|
а что с этим? да, в Java мы не можем реализовать дженерик-класс частично. зато, если кто-то решит воспользоваться нашим MyStruct, у него не будет проблем, ему не придется писать обертки и юзать их каждый раз, когда ему понадобиться g().
а связано такое поведение не "с тем, что мы работает во время компиляции и манипулируем типами, а не объектами.", т.к. ничто не мешало запретить такую возможность для шаблонов, просто не захотели/не посчитали нужным/решили, что так удобней |
|
Сообщ.
#5092
,
|
|
|
|
Цитата korvin @ ничто не мешало запретить такую возможность для шаблонов Я тебе запрещу! Это правильная и годная вещь. Добавлено Вот небольшой пример из "Современного проектирования" на эту тему: Цитата 1.8. Факультативные возможности, предоставляемые неполной конкретизацией Язык C++ придает стратегиям особую мощь, снабжая их интересным свойством. Если функция-член шаблонного класса никогда не используется, она не конкретизируется — компилятор вообще игнорирует ее, проверяя лишь синтаксические ошибки.5 Это дает главным классам возможность задавать и применять факультативные свойства классов стратегий. Например, определим функцию-член Switchprototype в классе widgetManager. ![]() ![]() // Код библиотеки template<template<class> class CreationPolicy> class WidgetManager : public CreationPolicy<Widget> { ... void switchPrototype(widget* pNewPrototype) { CreationPolicy& myPolicy = *this; delete mypolicy.GetPrototype(); myPolicy.setPrototype(pNewPrototype); } }; Возникающий контекст очень интересен. • Если пользователь конкретизирует класс WidgetManager с помощью класса стратегии Creator, поддерживающей работу с прототипами, можно использовать функцию Switchprototype. • Если пользователь конкретизирует класс WidgetManager с помощью класса стратегии Creator, не поддерживающей работу с прототипами, и попытается использовать функцию SwitchPrototype, во время компиляции возникнет ошибка. • Если пользователь конкретизирует класс WidgetManager с помощью класса стратегии Creator, не поддерживающей работу с прототипами, и не пытается использовать функцию Switchprototype, программа считается правильной. Все сказанное выше означает, что класс WidgetManager может использовать факультативные расширенные интерфейсы, но при этом продолжает правильно работать и с интерфейсами, обладающими более бедными возможностями, пока пользователь не попытается использовать определенные функции класса WidgetManager. |
|
Сообщ.
#5093
,
|
|
|
|
Цитата D_KEY @ Цитата ...пока пользователь не попытается использовать определенные функции класса WidgetManager. и получит жопу. да, очень "правильная и годная вещь" |
|
Сообщ.
#5094
,
|
|
|
|
Цитата korvin @ и получит жопу Очень оригинальная трактовка статической типизации, в мемориз однозначно. Переходом в run-time. Если мне будет нужен динамический полиморфизм, я им и воспользуюсь. В реализации могут быть, например, определены флаги, по которым я ориентируюсь, и типы, которые я использую. Как, например, определены итераторы в STL контейнерах. ![]() ![]() template<class T> class Impl { public: static const bool flag = /* что-то там */; typedef T some_type some_type f() { /* реализация */ } }; В специализированных специализациях some_type может быть объявлен как угодно. Ну, и потом, я могу захотеть наследовать реализацию ![]() ![]() template<class T> class A : public Impl<T> { }; А замещать статический полиморфизм динамическим жутко неэффективно с точки зрения производительности. Особенно доставляют всякие джавошарповские хэшеры и компараторы - тормоза да и только. |
|
Сообщ.
#5095
,
|
|
|
|
Цитата korvin @ и получит жопу. Почему? Он получит класс, который определяется переданной политикой. Если политика не подразумевает некоторую возможность ее и не будет в целевом классе. Или нужно объяснить что такое политика(стратегия)? |
|
Сообщ.
#5096
,
|
|
|
|
Цитата MyNameIsIgor @ Очень оригинальная трактовка статической типизации, в мемориз однозначно. интересно при чем тут статическая типизация? Добавлено Цитата MyNameIsIgor @ В реализации могут быть, например, определены флаги, по которым я ориентируюсь, и типы, которые я использую. Как, например, определены итераторы в STL контейнерах. ![]() ![]() template<class T> class Impl { public: static const bool flag = /* что-то там */; typedef T some_type some_type f() { /* реализация */ } }; В специализированных специализациях some_type может быть объявлен как угодно. в чем проблема-то? ![]() ![]() interface Impl<T> { void f(); } class DefaultImpl<T> implements Impl<T> { public static final boolean flag = true; public void f() { System.out.printf("Default (%s)\n", flag); } } class A<T> { private Impl<T> impl; public A(Impl<T> impl) { this.impl = impl; } public void use() { impl.f(); } } class Some {} class SomeImpl<T extends Some> implements Impl<T> { public void f() { System.out.println("Some"); } } class Other extends Some {} class Another extends Some {} class AnotherImpl<T extends Another> extends SomeImpl<T> { public void f() { System.out.println("Another"); } } public class Main { public static void main(String[] args) { A<String> stringA = new A<>(new DefaultImpl<String>()); A<Some> someA = new A<>(new SomeImpl<Some>()); A<Other> otherA = new A<>(new SomeImpl<Other>()); A<Another> anotherA = new A<>(new AnotherImpl<Another>()); stringA.use(); someA.use(); otherA.use(); anotherA.use(); } } Добавлено Цитата D_KEY @ Почему? потому что, он ожидает, что класс реализует g() |
|
Сообщ.
#5097
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ Почему? потому что, он ожидает, что класс реализует g() Почему? |
|
Сообщ.
#5098
,
|
|
|
|
Цитата MyNameIsIgor @ Ну, и потом, я могу захотеть наследовать реализацию ![]() ![]() template<class T> class A : public Impl<T> { }; и опять в чем проблема? ![]() ![]() class A<T> extends DefaultImpl<T> { private Impl<T> impl; public A(Impl<T> impl) { this.impl = impl; } public void use() { impl.f(); } } Добавлено Цитата D_KEY @ Почему? потому что в шаблоне есть g() |
|
Сообщ.
#5099
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ Почему? потому что в шаблоне есть g() Ну и что? Посмотри пример от Александреску. По-моему там все очевидно для клиента. Кроме того, это будет отражено в документации. Я, честно говоря, не понимаю, в чем проблема. |
|
Сообщ.
#5100
,
|
|
|
|
Цитата korvin @ в чем проблема-то? А сами не видите? Как я могу получить some_type в вашем коде? Где он у вас вообще? Или решили дурачка включить? С чего у вас void f()?И, да, на основе flag в плюсах я могу действовать в compile-time. Нужно ли пояснять, что в джаве это невозможно? Цитата korvin @ и опять в чем проблема? Не вижу в вашем примере никакого наследования реализации. Изобразите на джаве это ![]() ![]() template<class T> class Impl { public: T f(); }; template<class T> class A : public Impl<T> { }; class B {}; template<> class Impl<B> { public: int f(); B g(); }; A<B> a; B b = a.g(); int i = a.f(); Цитата korvin @ интересно при чем тут статическая типизация? Ну, потому что когда "пользователь попытается использовать определенные функции класса WidgetManager", компилятор сообщит об ошибке. А сделает он это потому, что С++ - статически типизированный язык. В свою очередь, вы этот факт прокомментировали как "получит жопу". Из чего следует вывод, что вы воспринимаете статическую типизацию как жопу. |