Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, mihailik, Вы писали:
C>>> Что мне делать, если я хочу отсортировать встроенный массив или вообще какой-то свой контейнер? Придумал! Копировать его в этот TList, а потом забирать назад! Прекрасное решение! M>>Встроенных типов не так много, легче простого написать небольшую библиотечку с функциями типа SortIntegerArray и т.п. WH>Да а потом SortMyCoolType1Array, SortMyCoolType2Array, SortMyCoolType3Array,... WH>А потом нам будет нужен бинарный поиск по отсортированому массиву, а потом удаление элементов при выполнение какого либо условия,...
Слабо отличающийся от твоего примера на шаблонах. Зачем повторять одно и тоже ????
И бинарный поиск и удаление делается элементарно.
M>>Или крутизна шаблонов как раз и заключается в работе со встроенными типами? WH>Не со встроеными, а со всеми. M>>Игрушечки какие-то WH>Эти игрушеччки сокращают размер кода в разы и значительно повышают надежность. Отсутствие возможностей для реализации элементарных смартпоинтеров использование которых не требует каких либо телодвижений и накладных расходов просто убивает.
А есть в С++ директива Implements которая говорит, что за реализацию определенных интерфейсов объекта отвечает объект являющийся полем данного объекта??? В С# нет. Тоесть для уже готовой реализации нужно для каждого объекта выполнять реализацию всех методов????
WH>Ну не возможно в таких условиях работать. Каменный век.
смартпоинтеров легко реализуются через наследование от TtypedObject или включение реализации любого интерфейса в наследнике от TComponent при этом мы получаем гибкость. Или включеннии объекта в спсок который при уничтожении вызывает деструктор каждого внедренного объекта.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Joker6413, Вы писали:
J>>Что за бред? Ты вообще понимаешь что такое конструктор? И что за указатель на класс? Ты про метакласс говоришь или все таки про объект класса? S>Я тебе очень рекомендую для прочтения Object Pascal Reference из комплекта Delphi. Тогда тебе станет понятно, о чем идет речь. Нельзя слепо применять термины в трактовке одного языка к другому языку. То, что в С++ не бывает виртуальных конструкторов и нет понятия "указатель на класс", не есть универсальное свойство ООП.
S> Слабо отличающийся от твоего примера на шаблонах. Зачем повторять одно и тоже ????
СТРОГАЯ ТИПИЗАЦИЯ эти слова тебе чтонибудь говорят? А еще имея информация о типах можно проводить оптимизации например можно узнать является ли тип POD типом и если да то можно использовать memcpy...
А уж как я реализовал сериализацию...
Этого достаточно для того чтобы класс умел себя сохранять/загружать из банарного потока.
Вот все что нужно ядру для того чтобы сериализовать вектора. Данная реализация может применяться рекурсивно что позволяест сериализовать вектора векторов.
Ну и где твоя дельфя?
S> А есть в С++ директива Implements которая говорит, что за реализацию определенных интерфейсов объекта отвечает объект являющийся полем данного объекта??? В С# нет. Тоесть для уже готовой реализации нужно для каждого объекта выполнять реализацию всех методов????
В С++ есть куда болие гибкие средства от банального наследования реализации
S> смартпоинтеров легко реализуются через наследование от TtypedObject или включение реализации любого интерфейса в наследнике от TComponent при этом мы получаем гибкость.
А если я не хочу мой класс ни от чего наследовать? А если мне нужны слабые ссылки? А если мне не нужен оверхед? А если.... В С++ я могу создать смартпоинтер с любыми необходимыми здесь и сейчас параметрами.
Например писал я OPC server там куча методов должны возвращать массивы созданные при помощи CoTaskMemAlloc. На С++ я за пять минут сотворил шаблон помошник который проверял былали выделена память, следил за выделеной памятью, инициализировал память и в случае чего вызывал деструкторы, а самое главное прикидывался массивом и уже когда все закончино и гарантировано не будет исключений я забирал заполненый массив и возвращал из функции.
Использование ваглядит примерно так
STDMETHODIMP COPCServer::GetItemProperties(
/* [in] */ LPWSTR szItemID,
/* [in] */ DWORD dwCount,
/* [size_is][in] */ DWORD *pdwPropertyIDs,
/* [size_is][size_is][out] */ VARIANT **ppvData,
/* [size_is][size_is][out] */ HRESULT **ppErrors
)
try
{
....
CoArray<CComVariant> data(dwCount);
CoArray<HRESULT> errors(dwCount);
....тут можно творить что угодно...
*ppvData=data.Detach();
*ppErrors=errors.Detach();
return S_OK;
}
com_catch_all()//Ловит определенный типы исключений, достает из них HRESULT и возвращает.
//Если прилетело не поймешь что просто возвращает E_FAIL
А тебе на дельфях слабо? S>Или включеннии объекта в спсок который при уничтожении вызывает деструктор каждого внедренного объекта.
Вот еще
Короче извращаться с нетипизированой памятью можно и на асме для этого не нужен ЯВУ, а дельфя именно на это звание претендует.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Sinclair, Вы писали:
S>Я тебе очень рекомендую для прочтения Object Pascal Reference из комплекта Delphi. Тогда тебе станет понятно, о чем идет речь. Нельзя слепо применять термины в трактовке одного языка к другому языку. То, что в С++ не бывает виртуальных конструкторов и нет понятия "указатель на класс", не есть универсальное свойство ООП.
А оно РЕАЛЬНО надо? Почему бы просто не сотворить абстрактную фабрику?
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Serginio1, Вы писали:
S> Но если я захотел изменить (добавить) функциональность для конкрентого типа, которая для других типов не нужна ????? Есть в шаблонах наследование ???
Есть, конечно. Надо — пользуйся. Есть и наследование и более экономный механизм — специализация. Конкретную специализацию можно и допилить, если не устраивает обобщённый вариант. Нередко это закладывается ещё при проектировании шаблона.
Ну, например:
template<typename T>
class X
{
T m_t;
// ...public:
void some_operation();
};
// Это - общая структура операции для всех типов-аргументов Ttemplate<typename T>
void X<T>::some_operation() { m_t = m_t * 2; }
// Теперь сделаем специализацию для some_operation()
// для некоего отдельного типа, например inttemplate<>
void X<int>::some_operation() { m_t = m_t / 2; }
// Всё, теперь для такого экземпляра:
X<int> x1;
// ... в вызове some_operation(), m_t будет делиться на 2, а для таких:
X<float> xf; X<double> xd;
// m_t будет умножаться на 2
S> Объясню подробнее. Есть база 1С. На основании метаданных можно построить объекты для прямого доступа к файлам опирающихся на несколько связанных таблиц от базового объекта. Решение через формирование исходников есть http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019. S> Как такую проблему можно решить через шаблоны????
Можно и исходники сгенерировать, только их скомпилить потом отдельно нужно.
Хотя, конечно, можно и не генерировать исходников, а просто воспользоваться чтением описания БД и компоновкой предварительно скомпилированных объектов, обрабатывающих доступ к отдельным полям.
Шаблоны могут помочь здесь тем, что позволят или сильно сократить объём генерируемого кода или вообще отказаться от какой-либо генерации дополнительным средством, ограничившись почти что одним только перечислением имён полей и их типов непосредственно в программе на C++, особенно, если воспользоваться ещё и препроцессором... сахара ради...
Проблема в другом, в том, что нужно ещё знать: кто и как результатами генерации будет пользоваться. Иначе зачем со всем этим возиться?
А потому лучше решать задачу с противоположной стороны. Не "от файлов", а "от программы". Не файлы, а вернее — внешние хранилища данных определяют структуру классов, а структура классов определяет наиболее приемлемые способы их хранения.
Поясню подход подробнее. Есть задача. Есть её объектная декомпозиция, сделанная исходя из требований задачи и квалификации проектировщика. Есть некое хранилище, к которому, возможно, надо адаптироваться. Или десяток разных хранилищ, к которым тоже надо адаптироваться. Исходя из декомпозиции строим адаптеры к той или иной БД. Всё!
S> Это не "Понты" а практический вопрос, т.к. по понятной причине не имею с ними практики. Заранее благодарен за ответ.
Ну, если помог, то — пожалуйста.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, WolfHound, Вы писали:
WH>А уж как я реализовал сериализацию...
Вот по поводу сериализации — не надо. В дельфи она уже есть. Достаточно объявить проперть как published, чтобы ее можно было сериализовать автоматом. Это отстает от .NET, но извините — технологии уж 10 лет как. А в плюсах ты, как ни парься, должен писать код руками.
Со всем остальным согласен
... << RSDN@Home 1.1 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, WolfHound, Вы писали:
WH>А оно РЕАЛЬНО надо? Почему бы просто не сотворить абстрактную фабрику?
Можно. Но зачем? Она уже сделана!
Поясняю:
Фактически, объявление каждого класса в Delphi автоматически вводит 2 типа и 1 объект.
Первый тип — собственно сам класс (например TMyClass). Второй тип — метакласс, class of TMyClass, он невидим до объявления, тем не менее можно считать, что он есть. Существует синглтон-объект этого типа, собственно TMyClass.
В случае наличия виртуального конструктора, этот метакласс автоматически становится фабрикой. Весь прикол в том, что иерархия фабрик в точности повторяет иерархию классов! Я навскидку не скажу, как это воспроизвести в плюсах. Дело в том, что тот самый метод фабрики, который и производит полезные объекты, (виртуальный конструктор) возвращает разные типы.
Если у меня есть class TA с constructor Create(I: Integer); virtual и class TB(TA), и объявлены метаклассы TAClass и TBClass, то:
TAClass.Create имеет тип результата TA;
TBClass.Create имеет тип результата TB;
при этом в люое место, где ожидается TAClass можно передать TBClass, как будто он является его наследником (что и делает его абстрактной фабрикой).
Собственно, вся VCL построена ровно на constructor TComponent.Create(AOwner: TComponent); virtual;
Другие фабрики используются реже (есть в коллекциях). Именно она позволяет читать DFM файлы: по имени класса находится указатель на его метаобъект, и на нем вызывается Create. При этом
1. сам Create не теряет типизации. Он возвращает объект нужного класса. Поэтому, без введения нового метода я могу потребовать где-то TControlClass вместо TComponentClass, и компилятор будет знать, что вызов на нем Create(AOwner) вернет TControl.
2. Мне не нужно писать код этих методов — я пишу только ту часть, которая относится к инициализации объекта. Поэтому я застрахован от ошибок. Грубо говоря, в плюсах я рискую написать в TA* TBClass::Create(int I) {return new TC(I);}
3. Любые изменения в иерархии классов автоматически отражаются в иерархии метаклассов.
Кроме всего этого, я имею бонус в виде возможности вставить в метакласс методы, как статические, так и виртуальные. Их можно вызывать и на объектах, и на классах.
Таким образом, за мелкими деталями реализации следит компилятор. И это приятно. Всякий паттерн хорош; а тот, который поддержан языком — хорош вдвойне. Ибо эффективен.
... << RSDN@Home 1.1 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
WH>>А уж как я реализовал сериализацию... S>Вот по поводу сериализации — не надо. В дельфи она уже есть. Достаточно объявить проперть как published, чтобы ее можно было сериализовать автоматом. Это отстает от .NET, но извините — технологии уж 10 лет как. А в плюсах ты, как ни парься, должен писать код руками.
Особенно мне нравится вот это.(дельфи под рукой нет из хелпа к билдеру)
No constructors or destructors are allowed in a __published section. Properties, Pascal intrinsic or VCL or CLX derived data-members, member functions, and closures are allowed in a __published section. Fields defined in a __published section must be of a class type. Properties defined in a __published section cannot be array properties. The type of a property defined in a __published section must be an ordinal type, a real type, a string type, a small set type, a class type, or a method pointer type.
К томуже страдает инкапсуляция, да и с производительность если мне не изменяет сколероз проблемы...
Моя сериализация расширяется легко и на что угодно, поддерживает версии...
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Поля публиковать особого смысла нет. Это как раз и есть потеря инкапсуляции. Дырка для ссылок на объекты оставлена для специального случая дизайна форм. Я бы сделал по-другому, но в старые времена предпочли добавить такую штуку усложнению среды. WH>К томуже страдает инкапсуляция,
В каком-то смысле да. Но там вся система сериализации строится на предположении, что набор значений хранимых свойств однозначно определяет состояние объекта. WH>да и с производительность если мне не изменяет сколероз проблемы...
Это верно. Я бы с большим удовольствием получил документацию на Dll компилятора, которая используется в среде Delphi. Это позволило бы генерировать код в рантайме, и он был бы не менее быстрым, чем плюсовый. Но увы. WH>Моя сериализация расширяется легко и на что угодно, поддерживает версии...
Не знаю, что такое "на что угодно", но про поддержку версий — согласен. Ясно, что при изменении описания класса мы огребем... Хотя, если честно, это все-таки архитектурный косяк. Вот мы сериализовали обезъяну, а потом восстановили ее как человека. Ну не бред ли? Это не описание человека. Даже если оба класса случайно называются "примат". Но это долгая дискуссия теоретического плана. А на практике удобнее иметь версионность в сериализаторе.
... << RSDN@Home 1.1 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Поля публиковать особого смысла нет. Это как раз и есть потеря инкапсуляции. Дырка для ссылок на объекты оставлена для специального случая дизайна форм. Я бы сделал по-другому, но в старые времена предпочли добавить такую штуку усложнению среды.
Зачем публиковать? Мой сериализатор может сериализовать приватные поля.
WH>>Моя сериализация расширяется легко и на что угодно, поддерживает версии... S>Не знаю, что такое "на что угодно",
А привел кусок кода который включает поддержку сериализации vector'ов. Аналогично можно добавить сериализацию любого контейнера лаже не существовавшего в момент написания библиотеки. S>но про поддержку версий — согласен. Ясно, что при изменении описания класса мы огребем... Хотя, если честно, это все-таки архитектурный косяк. Вот мы сериализовали обезъяну, а потом восстановили ее как человека. Ну не бред ли? Это не описание человека.
Обычно происходит так: Описаваем человека имя, фамилия, пол, рост, вес. Черед некоторое время выяснилось что надо еще цвет глаз, цвет волос. Еще через некоторое время понадобился IQ... S>Даже если оба класса случайно называются "примат". Но это долгая дискуссия теоретического плана. А на практике удобнее иметь версионность в сериализаторе.
Во-во. Особенно если не делать из обезьяны человека.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Зачем публиковать? Мой сериализатор может сериализовать приватные поля.
Дельфийский тоже. Для этого оставлен ровно такой же выход — можно перегрузить некий метод, и в нем сделать все, что захочется. Именно так сериализуются всякие штуки типа картинок, у которых нет публичных свойств, отвечающих за контент. Просто часть работы уже берет на себя компилятор. WH>А привел кусок кода который включает поддержку сериализации vector'ов.
В дельфи коллекции тоже сериализуются. WH> Аналогично можно добавить сериализацию любого контейнера лаже не существовавшего в момент написания библиотеки.
Ну естественно. Ведь контейнер — это класс WH>Обычно происходит так: Описаваем человека имя, фамилия, пол, рост, вес. Черед некоторое время выяснилось что надо еще цвет глаз, цвет волос. Еще через некоторое время понадобился IQ...
Ну естественно. При программировании неизбежно в какой-то момент начинает требоваться IQ
На самом деле я говорил о том, что тот "человек", который был тогда, и тот, который теперь — это два разных класса. В рамках С++ нет такого понятия, как эволюция класса. С этой точки зрения более правильным является создание нового класса, который оборудован конструктором от старого (который никуда не делся!). И мы десериализуем старый объект, конвертируем в новый, а потом убиваем. Но практически, как я уже сказал, версионность запрограммировать проще.
Сериализация, а точнее persistence — это вообще достаточно плохо исследованная область ООП.
... << RSDN@Home 1.1 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Joker6413, Вы писали:
J>То есть реализации методов нет но сконструировать можно, хоть указывает черт знает куда но можно использовать? Так в C еще проще было пишу void *ptr = 0; и опа! у меня создан объект абстрактного класса? Могу его пользовать...
Не чёрти-куда, а на заглушку. Которая сообщит об ошибке, если программись проморгает. Интерфейсы не сразу появились.
J>Что за бред? Ты вообще понимаешь что такое конструктор? И что за указатель на класс? Ты про метакласс говоришь или все таки про объект класса?
Есть экземпляры класса, есть класс с методами, свойствами, событиями, конструкторами и деструктором.
Указатель на класс — это типа ссылка на экземпляр, переменная, имеющая тип того или иного класса.
Здравствуйте, Joker6413, Вы писали:
S>>Я тебе очень рекомендую для прочтения Object Pascal Reference ...
J>Ладно сорри, увлекся holy war...
Ну правда, как можно рассуждать о другом языке (синтаксисе, шаблонах решений и т.п.), элементарно с ним не познкамившись... Надо книжку почитать, пописать что-нить, потом уже сравнивать, но не в плоскости хорошо-плохо (потому как выливается в привычно-не привычно), а в плоскости "что соответствует/похоже" и как это можно применить.
Здравствуйте, WolfHound, Вы писали:
WH>Производительность. Типобезопасность. Гарантия удаления объекта. WH>Нука напиши как будут выглядить удаление группы объектов в твоейсистеме на дельфях? WH>...
Ну, например, используя TCollection и TCollectionItem.
Делаем свой итем, если не нужно бОльшей функциональности, а для примера — не нужно, то коллекцию не трогаем.
type
TMyItem = class(TCollectionItem)
...
end;
теперь создаём, и так далее...
var
C: TCollection;
Item: TMyItem;
begin
C := TCollection.Create(TMyItem);
Item := C.Add; // Создаём и добавляемwith Item do
begin// Модифицируемend;
C.Clear; // Удаляем с гарантией корректностиfor i := 0 to C.Count - 1 do
with C.Items[i] do
begin// Перебираемend;
Здравствуйте, centurn, Вы писали:
C> Да разница, собственно, в том, что драйвер и операционку ты просто никак на делфях не напишешь, принципиально. Ну кроме, возможно, того извращенческого маневра, что тут про драйвера говорили...
Это не проблема языка, это проблема конкретной реализации. Ну не позционирует Борланд свой этот инструмент, как на все случаи жизни...
C>А в шутере нужна максимальная производительность, которой в делфях и не пахнет. И дело даже не в качестве компилятора, а в том, что в С++ можно более тонко управлять тем, что тебе сделает компилятор.
Ой, неправда. Оптимизатор кода и в Дельфи есть, и неслабо оптимизирует. А если вопрос в том, где больше не всякому понятных галочек и рюшечек, так...
C> И на надо платить за то, что тебе не сейчас не нужно — это было и остается чуть ли не самым главным при развитии С++. И главное — не в ущерб функциональности.
Для С++ — да, возможно. Не спорю. Дельфи тоже в трёх редакциях поставляется. Покупаем стандарт, самую дешёвую, и юзаем Сеть, покупаем библиотеки по мере необходимости.
C> Короче, шутер на делфах можно сделать, но на это уйдет намного больше времени, чем на С++, ...
А потому, что надо будет найти .pas эквиваленты граф. бибилиотеки (DirectXx, OpenGlx), теорию изучить... А если это уже есть, найдено, тогда неправда ваша.
C> ...и будет этот шутер похож на слайд-шоу под аккомпанемент жутко свопящего винта.
Не будет. Это же дуалистический принцип использования сельскохозяйственных орудий на гидроповерхности...
C> ...Во-первых, я задолбался переводить структурки, используемые для общения с NetBios, с С на Pascal (кстати, С-шные структырки были в хелпе по WinAPI, поставляемом с Делфями, других я не нашел).
И чья это проблема? Языка? IDE? Борланда? Или моя? Вот, вот! Производители этих всяких API, пользуясь своей монопольность, чхать хотели на программистов-дельфинистов... Не замечаете аналогию с ОС?
C> ... А во-вторых в парочке мест я уже, грязно матерясь, просто сорвался на ассемблерные вставкм, т.к. не хватило терпения воротить все эти конструкции на паскале...
Всё же это от незнания либо от цейтнота, когда "давай, давай, чего телешся...".
C> И еще, раз уж меня потянуло кнопки понажимать... C>... Я не буду по этому поводу приводить особых аргументов, т.к. удобство все-таки понятие чисто субъективное, ...
И что из этого следует? Всё то же — монополизм на API. А как же разные подходы, взгляд со стороны, альтернатива?
C>И еще мысль: практически не бывает "чистого" GUI, обычно за ним стоит еще нетривиальный код (иначе вообще непонятно, зачем нужен нужен язык программирования).
Соглашусь, что код стоит. Несомненно. В то же время есть абстракция, когда я скажу "лабел", у всех в мозгу возникнет почти одинаковый образ.
Здравствуйте, WolfHound, Вы писали:
WH>Особенно мне нравится вот это.(дельфи под рукой нет из хелпа к билдеру)...
Ну сказано же, 10 лет, тянут совместимость, как резину.
А вот плюнули на неё и перевели бы XML — можно было бы и арраи сериализовать, и ещё что...
WH>Моя сериализация расширяется легко и на что угодно, поддерживает версии...
Хи-хи, так в C# это заложено изначально, как требование. Им тянуть совместимость не надо... Поживём-ка хотябы и лет пять, посмотрим...
Здравствуйте, WolfHound, Вы писали:
WH> ... А если надо вызывать несколоко функций залпом? Как на дельфях делать будешь?
Метод напишу. И вызову. Вариант 2: базовый класс.
И разговор этот из плоскости "поиск аналогий".
WH>Запомни это не в С++ нет чегото что есть в дельфе это в дельфе нет много чего что есть в С++.
С++ — типа язык, эквивалент этому — то, что называют язык Object Pascal.
Дельфи — это конкретная реализация, (ещё FreePascal, BP,...) аки Студия, Билдер, gcc. Одно плохо — мало этих реализаций OP, и нет поддержки на уровне ОС. А напиши кто ОС, взяв за базу синтаксис OP, то получился бы ... такой же монстр, как Cxxx...
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, DOOM, Вы писали:
DOO>>По-моему есть warning. Но сейчас сказать точно не могу. WH>Зачем варнинг? Это же стопроцентная ошибка.
Ну, не совсем. Дело в том, что в Delphi в любом случае вполне законным способом можно сконструировать объект абстрактного класса. Поэтому они и сделали Warning, а не Error — толку бы все равно не было.
Вообще, конечно, на мой взгляд, тут у них косяк. Я, когда столкнулся с этим их невнятным исключением, вынужден был слегка похакать, в результате чего и напсиал свою статью. Ибо есть довольно-таки трудноуловимые ситуации, которые бы борланду было не так и сложно разрулить.
... << RSDN@Home 1.1 beta 2 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.