Здравствуйте, Трурль, Вы писали:
VD>>Спроектировать большую систему в терминах модулей просто невозможно. Т>А ничего, что самые большие системы именно в терминах модулей и проектировались?
Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
Здравствуйте, deniok, Вы писали:
D>Ага. Особенно удачно там реализовано наследование. Посредством, очевидно, суффикса Ex. D>
D>WNDCLASSEX -> WNDCLASS
D>
Наследование как не странно реализовано не плохо. Только похоже не на С++, а на Смолток. WNDCLASSEX и WNDCLASS — это как раз не наследование. Это просто новая версия внутренней структуры. А вот сам класс окна там очень даже наследуется. Точнее сабкласится. Можно даже динамически тип изменять.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Odi$$ey, Вы писали:
VD>>Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
OE>winapi — ООП? хм..
Чистеший. Только реализован средствами С в котором это выглядит несколько странно. Но по сути проектирование ведется на уровне объектов. Они так и называются: объекты ядра, объекты GDI...
По сути присутсвуют все атрибуты ООП — полиморфизм, инкапсуляция, объекты с состояниями. Даже посылка сообщений кое где присутствует .
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Arioch, Вы писали:
OE>>winapi — ООП? хм.. A>Самыё что ни на есть, ордни объекты (windows handles) послыают другим сообщения — чистеший ООП в духе Smalltalk'a
сообщение посылает совершенно левая процедура, одним из параметров которой является handle, методов у handle нету, состояния тоже, так как если считать состояние его значение, то тогда кроме ОПП вообще никакого другого программирования нет
OE>>>winapi — ООП? хм.. A>>Самыё что ни на есть, ордни объекты (windows handles) послыают другим сообщения — чистеший ООП в духе Smalltalk'a
OE> сообщение посылает совершенно левая процедура,
не левая, а указанная в свойстве окна при создании процедура обработки сообщений
OE> одним из параметров которой является handle,
this является неявным параметром, но его как-то трудно передавать неявно в классических DLL'ях.
Иначе был бы неявным (но что бы это по сути меняло?)
OE> методов у handle нету,
А обязаны быть?
OE> состояния тоже,
А что такое GetWindowText? GetWindowLong ? http://msdn2.microsoft.com/en-us/library/aa453183.aspx http://msdn2.microsoft.com/en-us/library/ms633584.aspx
Здравствуйте, Arioch, Вы писали:
OE>> сообщение посылает совершенно левая процедура, A>не левая, а указанная в свойстве окна при создании процедура обработки сообщений
в PostMessage можно засунуть _любой_ handle
OE>> одним из параметров которой является handle, A>this является неявным параметром,
это всего лишь подробность конкретной реализации ООП
A>но его как-то трудно передавать неявно в классических DLL'ях. A>Иначе был бы неявным (но что бы это по сути меняло?)
Структура данных «класс» внешне похожа на структуру в языке Си или запись в Паскале, в котором кроме данных (свойства) также содержались функции их обработки (методы). Вдобавок класс поддерживает такие свойства как наследование, полиморфизм и отчасти — инкапсуляцию. Объектное программирование противопоставляется процедурному программированию, где данные и подпрограммы (процедуры, функции) их обработки формально не связаны.
imho winapi — типичное процедурное программирование, handle отдельно, GetWindowText отдельно, ничем кроме статьи в msdn они не связаны, можно засунуть в GetWindowText handle от открытого файла. В ООП у чего-то относящегося к файлу просто не было бы метода GetWindowText, а если брать handle вообще, которые могут быть оконные, файловые и еще всякие разные, то у такого объекта мог быть только соответствующий имеющий смысл набор методов.
Никакого такого соответствия между handle и функциями их принимающими в winapi не наблюдается.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Re[6]: Так в чем же принципиальные отличия ФП от ИП?
OE>>> сообщение посылает совершенно левая процедура, A>>не левая, а указанная в свойстве окна при создании процедура обработки сообщений OE>в PostMessage можно засунуть _любой_ handle
Равно и с Smalltalk'e можно послать любое сообщение любому объекту.
OE>>> одним из параметров которой является handle, A>>this является неявным параметром, OE>это всего лишь подробность конкретной реализации ООП
Разумеется. Поэтому будет handle параметром или нет — не важно.
A>>но его как-то трудно передавать неявно в классических DLL'ях. A>>Иначе был бы неявным (но что бы это по сути меняло?) OE>да, реализация ООП, например с помощью неявного this, поменяла бы процедурный подход на объектный
Т.е. все чем процедурный подход отличается от объектного — это неявность this. вот блин...
Интересно как выглядит CORBA в двоичной части, до разных сахарных оберток для языков — там тоже двочино ссылка на объект передается как-то неявно ?
OE>
OE>Структура данных «класс» внешне похожа на структуру в языке Си или запись в Паскале, в котором кроме данных (свойства) также содержались функции их обработки (методы). Вдобавок класс поддерживает такие свойства как наследование, полиморфизм и отчасти — инкапсуляцию. Объектное программирование противопоставляется процедурному программированию, где данные и подпрограммы (процедуры, функции) их обработки формально не связаны.
Это формальное связывание нужно только для процедурно-ориентированных ООЯ, но не для всех ООЯ.
Объекты представляют собою неполную информацию о реальных сущностях предметной области
Выхывая GetWindowText я не знаю и не хочу знать как реализован STATIC (просто текст), редактируемый EDIT, кнопка и т.д.
Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и методов класса-предка
...т.е. вызов предыдущей функции обработки сообщений, subclassing
....при необходимости, новые свойства и методы
методы — или сообщения! — обработка новых сообщений в новой функции обработки сообщений
свойства — GetWindowLong
Полиморфизмом называют явление, при котором классы-потомки могут изменять реализацию метода класса-предка, сохраняя его сигнатуру
Сигнатура тут одна — функция обработки сообщений
Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как чёрный ящик — пользователь класса должен видеть и использовать только интерфейс
Отправляя сообщение, я использую стандартный интерфейс, рассматривая объект как чёрный ящик
OE>imho winapi — типичное процедурное программирование, handle отдельно, GetWindowText отдельно,
GetWindowText можно рассматривать как синтаксический сахар поверх SendMessage(WM_getCaption) или как-то так.
OE>Никакого такого соответствия между handle и функциями их принимающими в winapi не наблюдается.
HWND и HANDLE — разные типы, хотя для C конечно разных типов почти не существует. Но это ограничение реализации, которая должны быть совместимой с Pure C и DLL export
Любое сообщение может быть послано любому объекту; объект-получатель определяет, является ли это сообщение правильным, и что надо сделать, чтобы его обработать.
Таким образом Smalltalk не является процедурно-ориентированным ООЯ, в нем нет методов жестко привязанным к типам как в C++/Object Pascal/Java/etc http://ru.wikipedia.org/wiki/Objective-C
Еще одной из особеностей языка является то, что он message-oriented в то время как С++ — function-oriented. Это значит, что в нем вызовы метода интерпретируются не как вызов функции (хотя к этому обычно все сводится), а именно как посылка сообщения (с именем и аргументами) объекту, подобно тому, как это происходит в Smalltalk-е.Такой подход дает целый ряд плюсов — так любому объекту можно послать любое сообщение
Здравствуйте, Odi$$ey, Вы писали:
VD>>Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
OE>winapi — ООП? хм..
Важное слово выделено. Интерфейс Win API — реазультат объектно-ориентированного проектирования. Выраженный теми средствами, которые были в наличии. Про наследование врать не буду — наследование в данном случае внутренняя деталь реализации, о которой мы не знаем.
* инкапсуляции — дофига. Доступ к полям объектов мы имеем только через открытые функции.
* полиморфизм — почти любой хендл поддерживает операции CloseHandle и WaitFor. При этом происходит правильный close, т.е. это именно полиморфизм. В посиксах с этим ещё лучше — любой объект — файл — в терминал ООП это означает, что файл — абстрактный базовый класс, и есть реализации для сокета, для пайпа, для файла на диске.
Здравствуйте, Odi$$ey, Вы писали:
OE>>> сообщение посылает совершенно левая процедура, A>>не левая, а указанная в свойстве окна при создании процедура обработки сообщений
OE>в PostMessage можно засунуть _любой_ handle
Ага, значит просто PostMessage объявлен в типе object
A>>но его как-то трудно передавать неявно в классических DLL'ях. A>>Иначе был бы неявным (но что бы это по сути меняло?)
OE>да, реализация ООП, например с помощью неявного this, поменяла бы процедурный подход на объектный
Даже странно такое слышать от человека с рейтингом 47
Можно ведь реализовать все приколы ООП даже в ассемблере, причём даже если его компилятор не знает, что такое функция (но сами call/ret имеются)
OE>
OE>Структура данных «класс» внешне похожа на структуру в языке Си или запись в Паскале, в котором кроме данных (свойства) также содержались функции их обработки (методы). Вдобавок класс поддерживает такие свойства как наследование, полиморфизм и отчасти — инкапсуляцию. Объектное программирование противопоставляется процедурному программированию, где данные и подпрограммы (процедуры, функции) их обработки формально не связаны.
Я могу (и делал) с помощью структур на ассемблере реализовать полиморфизм и наследование. Правда не очень-то приятно это делать (ну, не знаю, может кто-то знает, как приятно...)
OE>imho winapi — типичное процедурное программирование, handle отдельно, GetWindowText отдельно, ничем кроме статьи в msdn они не связаны, можно засунуть в GetWindowText handle от открытого файла. В ООП у чего-то относящегося к файлу просто не было бы метода GetWindowText, а если брать handle вообще, которые могут быть оконные, файловые и еще всякие разные, то у такого объекта мог быть только соответствующий имеющий смысл набор методов. OE>Никакого такого соответствия между handle и функциями их принимающими в winapi не наблюдается.
И каков же будет результат работы у GetWindowText с handle от файла?
Опять же, подход ОО, но вот синтаксис не ОО. Разница ведь в том, что внутри, а не в синтаксисе.
Re[7]: Так в чем же принципиальные отличия ФП от ИП?
Здравствуйте, Arioch, Вы писали:
OE>>>> сообщение посылает совершенно левая процедура, A>>>не левая, а указанная в свойстве окна при создании процедура обработки сообщений OE>>в PostMessage можно засунуть _любой_ handle
A>Равно и с Smalltalk'e можно послать любое сообщение любому объекту.
не знаком со Smalltalk-ом в отличии от winapi
A>Т.е. все чем процедурный подход отличается от объектного — это неявность this. вот блин...
это создает связь между данными и "их" методами
A>Интересно как выглядит CORBA в двоичной части, до разных сахарных оберток для языков — там тоже двочино ссылка на объект передается как-то неявно ?
опять же не знаком с CORBA-й, поэтому говорю не о ней, а о winapi
OE>>
OE>>Объектное программирование противопоставляется процедурному программированию, где данные и подпрограммы (процедуры, функции) их обработки формально не связаны.
A>Это формальное связывание нужно только для процедурно-ориентированных ООЯ, но не для всех ООЯ.
A>
Объекты представляют собою неполную информацию о реальных сущностях предметной области
A>Выхывая GetWindowText я не знаю и не хочу знать как реализован STATIC (просто текст), редактируемый EDIT, кнопка и т.д. A>
Наследованием называется возможность порождать один класс от другого с сохранением всех свойств и методов класса-предка
A>...т.е. вызов предыдущей функции обработки сообщений, subclassing A>
....при необходимости, новые свойства и методы
A>методы — или сообщения! — обработка новых сообщений в новой функции обработки сообщений A>свойства — GetWindowLong A>
Полиморфизмом называют явление, при котором классы-потомки могут изменять реализацию метода класса-предка, сохраняя его сигнатуру
A>Сигнатура тут одна — функция обработки сообщений A>
Инкапсуляция — это принцип, согласно которому любой класс должен рассматриваться как чёрный ящик — пользователь класса должен видеть и использовать только интерфейс
A>Отправляя сообщение, я использую стандартный интерфейс, рассматривая объект как чёрный ящик
имеет место некоторое подобие, похожие потребительские свойства, но ... как бы это сказать, то что я умею ходить на ципочках не делает меня балериной
OE>>Никакого такого соответствия между handle и функциями их принимающими в winapi не наблюдается. A>HWND и HANDLE — разные типы, хотя для C конечно разных типов почти не существует. Но это ограничение реализации, которая должны быть совместимой с Pure C и DLL export
typedef HANDLE HWND; это костыли, но легко найти и более чистый пример —
Любое сообщение может быть послано любому объекту; объект-получатель определяет, является ли это сообщение правильным, и что надо сделать, чтобы его обработать.
замечательно, объект сам обрабатывает приходящие сообщения, в winapi-же над "объектами" работают левые процедуры
Здравствуйте, FDSC, Вы писали:
FDS>И каков же будет результат работы у GetWindowText с handle от файла?
собственно и я о том же, было бы это ОПП это просто было бы невозможно
FDS>Опять же, подход ОО, но вот синтаксис не ОО. Разница ведь в том, что внутри, а не в синтаксисе.
побарабану что там внутри, везде собственно одно и тоже — машинные коды, разница в том как это выглядит снаружи, для пользователя
Здравствуйте, deniok, Вы писали:
D>Слушайте, по-моему здесь все обалдели.
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП.
Здравствуйте, deniok, Вы писали:
D>Слушайте, по-моему здесь все обалдели.
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП.
D>Например, ODBC. Хэндлы есть — инкапсуляция. Функции на хэндл вызываются — сообщения.
Ну и чего в этом плохого? ОО-проектирование, ОО-декомпозиция — мощная штука, почему бы авторам библиотек её не использовать? ОО как способ думать и проектировать.
Как писал Страуструп, объектно-ориентированный язык — язык, на котором удобно писать ОО-программы. Но это не значит, что их нельзя писать на других языках. Просто то, что в том же С++ решается само здесь оставляется на самодисциплину пользователя и дополнительный код. Этакий "ООП без сахара".
А пользователь библиотеки, который понимает задумку авторов видит не набор случайных функций, а методы объектов. И он уже сам понимает, в какую функцию какой хендл передавать можно, а какой нельзя
Здравствуйте, Odi$$ey, Вы писали:
OE>собственно и я о том же, было бы это ОПП это просто было бы невозможно
В скриптовых языках, которые как-будто вполне ООП, проверки идут в рантайме. Т.е. у любого объекта можно вызвать любой метод. Да ещё и с любыми аргументами.
Делай что должно, и будь что будет
Re[8]: Так в чем же принципиальные отличия ФП от ИП?
Здравствуйте, deniok, Вы писали:
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП. D>Например, ODBC. Хэндлы есть — инкапсуляция. Функции на хэндл вызываются — сообщения.
Так может потому так резко и распространились ОО-языки (т.е. языки с поддержкой ООП), потому что люди уже реально использовали ООП на неудобных для этого средствах, а потом получили средства. позволяющие делать то же, но удобнее и надежнее?
Здравствуйте, deniok, Вы писали:
D>Слушайте, по-моему здесь все обалдели.
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП.
Здравствуйте, fmiracle, Вы писали:
F>Так может потому так резко и распространились ОО-языки (т.е. языки с поддержкой ООП), потому что люди уже реально использовали ООП на неудобных для этого средствах, а потом получили средства. позволяющие делать то же, но удобнее и надежнее?
Не так уж и резко они появились.
Даже если считать от момента появления С++ (1983), прошел десяток лет,
прежде чем что-то реально сдвинулось.
А если считать от Симулы, то вообще не быстро все произошло
Здравствуйте, Odi$$ey, Вы писали:
OE>winapi — ООП? хм..
На самом деле, в WinAPI действительно чётко прослеживается ООП-подход. ООП базируется на трёх китах — инкапсуляция, наследование и полиморфизм. Всё это в WinAPI есть.
Инкапсуляция
WinAPI инкапсулирует объекты с помощью хэндлов, причём эта инкапсуляция получается намного сильнее, чем в типичной программе на C++. Мы не только ничего не знаем о внутреннем устройстве объектов, которые скрываются за хэндлами, — мы не знаем также их размер и местоположение. Объекты, с которыми мы работаем на уровне WinAPI, очень тяжело "испортить", перезаписав их память, вызвав для них неправильный метод и т. п. По сути дела, единственный способ сделать что-либо с объектом — это использовать связанный с ним API, то есть его интерфейс. Таким образом, в WinAPI очень чётко прослеживается разделение интерфейса (API) и реализации — это и есть инкапсуляция.
Наследование
В WinAPI наследование наиболее ярко проявляется в случае с оконной системой. Сравним два фрагмента.
1. Гипотетический оконный API на C++:
// Создаём класс окна для нашей программы...class CMyWindow : public CDefWindow
{
virtual int HandleMessage(...)
{
// Обрабатываем сообщение.return CDefWindow::HandleMessage(...);
}
};
CWindowFactory::RegisterClass(CLASS(CMyWindow));
// ...и объект этого класса.
CDefWindow *pWnd = CWindowFactory::Create(_T("CMyWindow"), ...);
2. WinAPI:
// Создаём класс окна для нашей программы...
LRESULT CALLBACK MyWindowProc(...)
{
// Обрабатываем сообщение.return DefWindowProc(...);
}
WNDCLASS wc;
wc.lpfnWndProc = MyWindowProc;
wc.lpszClassName = _T("CMyWindow");
RegisterClass(&wc);
// ...и объект этого класса.
HWND hWnd = CreateWindow(_T("CMyWindow"), ...);
Как говорится, найдите 10 отличий. С точки зрения синтаксиса фрагменты, безусловно, различны. Но с точки зрения семантики разницы нет никакой.
В этой связи я не очень понимаю аргумент о том, что можно передать функции GetWindowText любой хэндл. Вот например:
HFONT hFont;
GetWindowText(hFont, ...); // ошибка
GetWindowText((HWND)hFont, ...); // всё ОК
CFont *pFont;
pFont->GetWindowText(...); // ошибка
((CWnd*)pFont)->GetWindowText(...); // всё ОК
Разница, опять же, только в синтаксисе.
Полиморфизм
Полиморфизм тоже удобно рассмотреть на примере окон. Опять обратимся к гипотетическому примеру.
И в том, и в другом случае меня не заботит, к какому классу относится каждое из дочерних окон. Я могу задизаблить их все, используя единый интерфейс. Это и есть полиморфизм в действии. Аналогичным образом полиморфизм работает, когда мы ждём на произвольном объекте ядра с помощью WaitForSingleObject или, например, работаем со стримом через ReadFile/WriteFile — вне зависимости от того, файл ли это, пайп или драйвер.
Или рассмотрим такой пример:
SelectObject(hDC, hGdiObject);
По сути дела, это ничто иное как мультиметод. HDC скрывает от нас конкретную разновидность контекста (экран, принтер, память), а HGDIOBJECT — конкретную разновидность графического объекта (перо, кисть, фонт и т. д.). Мультиметоды не поддерживаются напрямую ни в C, ни в C++. Что не мешает использовать их в WinAPI.
Помимо основных концепций ООП, в WinAPI можно проследить и кое-какие паттерны проектирования. Например, CreateFile и CreateWindow — это по сути дела фабрики объектов. FindFirstFile/FindNextFile реализуют итератор. Окно, содержащее дочерние окна, может выступать как композит или декоратор — и в том, и в другом случае мы работаем с родительским окном, не заботясь о структуре окон внутри него. И т. д.
Что характерно, внутренняя реализация WinAPI очень удобно делается на классах. Например, оконная подсистема в Windows CE именно так и написана. Поверх WinAPI тоже очень легко положить "объектную модель". Многие популярные библиотеки, включая MFC и ATL/WTL — по сути дела тонкие обёртки над WinAPI. Они обеспечивают синтаксические удобства (вроде уничтожения объекта в деструкторе), но объектная ориентированность итоговой программы — не их заслуга. И это не случайно.
Одним словом, нужно провести чёткую грань между концепциями ООП и синтаксисом, поддерживающим эти концепции. Конценции ООП работают в WinAPI в полный рост. Ну а синтаксис — он уж какой есть.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Здравствуйте, VladD2, Вы писали:
VD>>>Спроектировать большую систему в терминах модулей просто невозможно. Т>>А ничего, что самые большие системы именно в терминах модулей и проектировались? VD>Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
Нуу.... Они почти ООП
Одна только оконная процедура в Windows без возможности передать контекст чего стоит. В Линуксе тоже не лучше дела — API для работы с локалями и временными зонами абсолютно анти-ООПшный.
Здравствуйте, deniok, Вы писали:
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП. D>Например, ODBC. Хэндлы есть — инкапсуляция. Функции на хэндл вызываются — сообщения.
Я подозреваю, что зависимость строго обратная — библиотека может стать большой и популярной, только если она грамотно спроектирована.
Причём бог с ним с ООП. Во многих областях можно прожить без наследования и полиморфизма. Другое дело — инкапсуляция. По сути дела то, что ты перечислил (хэндлы и функции, которые для них вызываются) — это она и есть. Так вот, без неё большую библиотеку просто не написать, потому что любое изменение в ней будет приводить к поломке существующего кода у юзеров, и очень быстро им это надоест.
Вообще инкапсуляция, разделение интерфейса и реализации — это универсальный принцип, он вовсю работает не только в программировании, но и в технике, да и вообще по жизни. Люди пользуются им не одну сотню лет. Чего, кстати, нельзя сказать про наследование и полиморфизм. Это уже гораздо более искусственные концепции. Наверно, поэтому и споров вокруг них гораздо больше.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Re[9]: Так в чем же принципиальные отличия ФП от ИП?
Здравствуйте, Draqon, Вы писали:
D>Это не левые процедуры. Это интерфейс объекта. D>То, что HANDLE файла и HANDLE консоли одинаково выглядят — это говорит о "типобезопасности", вернее, о её отсутствии. D>А не о том, что это не ООП.
если к "объектам" одного и того же типа — HANDLE — часть его "интерфейса" применять можно, а часть нельзя, то это по определению не интерфейс
Здравствуйте, SergH, Вы писали:
OE>>собственно и я о том же, было бы это ОПП это просто было бы невозможно SH>В скриптовых языках, которые как-будто вполне ООП, проверки идут в рантайме.
в скриптовых языках по другому просто нельзя сделать, что тут обсуждать
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, SergH, Вы писали:
OE>>>собственно и я о том же, было бы это ОПП это просто было бы невозможно SH>>В скриптовых языках, которые как-будто вполне ООП, проверки идут в рантайме.
OE>в скриптовых языках по другому просто нельзя сделать, что тут обсуждать
Ну дак кто мешает себе представить WinAPI как "скриптовый" интерфейс?
Никаких возражений по сути на это не последовало. Сдавайтесь сударь! Мы будем рады скрестить с вами шпаги в следующий раз А то начинается какое-то переливание из пустого в порожнее, отходы в сторону и т.п.
Здравствуйте, SergH, Вы писали:
OE>>в скриптовых языках по другому просто нельзя сделать, что тут обсуждать SH>Но это же не мешает им быть ОО? А тут почему-то мешает. Непорядок.
хорошо, спрошу так — когда ты пишешь в ООП стиле на С++ ты действительно делашь класс у которого метод aaaa() можно вызвать только если в конструктор передано "привет", метод bbb() только если в конструктор передано "пока", а метод сссс() есть, но только если его вызвать, в runtime все накроется медным тазом? Почему?
Ситуция практически один в один с типом HANDLE и методами его "интерфеса" SetConsoleCursorPosition, WriteFile и проч.
SH>Но честно говоря, я сейчас тебя вообще не понимаю. SH>Вроде Саша Шарыгин всё ну очень подробно описал и акценты расставил. Ну и я тоже немного тут http://www.rsdn.ru/Forum/Message.aspx?mid=2478206#2478206
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, SergH, Вы писали:
OE>>>в скриптовых языках по другому просто нельзя сделать, что тут обсуждать SH>>Но это же не мешает им быть ОО? А тут почему-то мешает. Непорядок.
OE>хорошо, спрошу так — когда ты пишешь в ООП стиле на С++ ты действительно делашь класс у которого метод aaaa() можно вызвать только если в конструктор передано "привет", метод bbb() только если в конструктор передано "пока", а метод сссс() есть, но только если его вызвать, в runtime все накроется медным тазом? Почему?
OE>Ситуция практически один в один с типом HANDLE и методами его "интерфеса" SetConsoleCursorPosition, WriteFile и проч.
Но это же не меняет сущности методов — они ОО. К тому же, попробуй их сделать нормальным ОО, когда у разных языков разные базовые объекты. Тут захочешь, а не сделаешь
Здравствуйте, Odi$$ey, Вы писали:
zE>хорошо, спрошу так — когда ты пишешь в ООП стиле на С++ ты действительно делашь класс у которого метод aaaa() можно вызвать только если в конструктор передано "привет", метод bbb() только если в конструктор передано "пока", а метод сссс() есть, но только если его вызвать, в runtime все накроется медным тазом? Почему?
OE>Ситуция практически один в один с типом HANDLE и методами его "интерфеса" SetConsoleCursorPosition, WriteFile и проч.
Через интерфейс handle тебе доступно несколько разных классов.
CreateFile это не конструктор, а фабрика классов.
При этом часть мотодов работает для всех хендлов — тут у нас полиморфизм.
А часть — не для всех — тут у нас типизация в рантайме.
OE>ну ты же первый был вот я с тебя и начал
Ты начал не с того сообщения. Я иногда слишком многословен и пишу лишнее. В данном случае, "программным" было сообщение про проектирование. Кстати, оно было раньше.
Здравствуйте, VladD2, Вы писали:
VD>>>Спроектировать большую систему в терминах модулей просто невозможно. Т>>А ничего, что самые большие системы именно в терминах модулей и проектировались?
VD>Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
Возможно, имеются в виду какие-нибудь "адские" проекты DoD (а может, парижское метро).
А о чем спор, собственно?
Разве модульное программирование несовместимо с ООП?
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, deniok, Вы писали:
D>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП.
Не любая конечно. Например, стандартная библиотека С написана черти как.
Но в общем-то так оно и есть. ООП он стал востребован не потому, что его навязали. Это паттерн который был настолько востребован, что превратился в парадигму.
D>Например, ODBC. Хэндлы есть — инкапсуляция. Функции на хэндл вызываются — сообщения.
Ага. А что есть инкапсуляция как не основная концепция ООП?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Так в чем же принципиальные отличия ФП от ИП?
Пойми. ООП — это не формальное описание, а парадигма, то есть то как мы смотрим на решение задачи. Вот если бы смотрели на окно виндовс как на данные которые в результате операции преобразуются в новы еданные, то мы бы имели ФП. А так как мы смотрим на окно как на объект получающий сообщения и изменяющий свое состояние, то мы имеем дело с ООП.
И ООП, и ФП и любая другая прадигма могут эмулироваться практически на любом языке. Просто языки с непостредственной поддержкой парадигмы позволяют писать более чистый и понятный код.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Odi$$ey, Вы писали:
FDS>>И каков же будет результат работы у GetWindowText с handle от файла?
OE>собственно и я о том же, было бы это ОПП это просто было бы невозможно
Если пользоваться твоим ошибочным определением, то, например, ML (строготипизированны, типобезопасный, ФЯ) является ООЯ, так как не допускает (вообще) ошибок связанных с типами. А С++ не ООЯ, так как допускает (и легко) ошибки связанные стипами. На С++ я без труда могу вызвать любой методу не у того объекта.
FDS>>Опять же, подход ОО, но вот синтаксис не ОО. Разница ведь в том, что внутри, а не в синтаксисе.
OE>побарабану что там внутри, везде собственно одно и тоже — машинные коды, разница в том как это выглядит снаружи, для пользователя
По барабану что за машинный код там внутри. Хоть интерпретатор. Важно то как мы осознаем программу. Если в терминах объектов, то это ООП, пуст даже и эмулируемый на не ООЯ.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, SergH, Вы писали:
SH>В скриптовых языках, которые как-будто вполне ООП, проверки идут в рантайме. Т.е. у любого объекта можно вызвать любой метод. Да ещё и с любыми аргументами.
Ага. В питоне даже this, точнее его аналог — self передается явно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, SergH, Вы писали:
OE>>winapi — ООП? хм..
SH>Важное слово выделено. Интерфейс Win API — реазультат объектно-ориентированного проектирования.
Кстати, когда проектировали NT (потомки которой сейчас и назваются Виндовс), то на полном серьезе рассматривали решение использовать С++ для написания этой ОС. Но отвергли это решение такак (гы-гы) в те времена считалось, что С++ создает неприемлемо большой оверхэд.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, konsoletyper, Вы писали:
C>>Одна только оконная процедура в Windows без возможности передать контекст чего стоит. K>Эй, а SetWindowLong/GetWindowLong что, отменили? Или в колбэк теперь не передаётся хендл того окна, которому пришло сообщение?
Отменили. Так как не один ты такой умный и SetWindowLong (кстати, правильно использовать SetWindowLongPtr) некоторые пакеты уже использовали для разных нужд. В результате, в ATL добавили хак с динамической кодогенерацией.
Здравствуйте, Cyberax, Вы писали:
C>Отменили. Так как не один ты такой умный и SetWindowLong (кстати, правильно использовать SetWindowLongPtr) некоторые пакеты уже использовали для разных нужд. В результате, в ATL добавили хак с динамической кодогенерацией.
Хак с динамической кодогенерацией добавили, потому что это наиболее эффективный способ. Но это не значит, что других способов решить проблему не существует. Например, можно использовать SetProp для назначения окну именованного свойства.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
D>>С помощью такой аргументации можно доказать, что почти любая объёмная библиотека, написанная на С в 80-90е годы — ООП.
FDS>Значит по сути и есть ООП
Как сказал Алан Кей (создатель Смоллтока), когда он создавал ООП, он имел в виду далеко не С++... :о)
А инкапсуляция, полиморфизм и даже наследование вообще к ООП не относится — это в равной мере есть и в ФП (в том же Хаскелле, например). Это более общие концепции, чем ООП или ФП.
ООП — это в большей мере активное взаимодействие объектов с постоянно меняющимся состоянием путём посылки сообщений друг другу... (имхо)
Здравствуйте, geniepro, Вы писали:
G>ООП — это в большей мере активное взаимодействие объектов с постоянно меняющимся состоянием путём посылки сообщений друг другу... (имхо)
В данном случае (WinAPI) мы видим и объекты. Согласен с замечанием
Здравствуйте, Alexander Shargin, Вы писали:
AS>Инкапсуляция
AS>WinAPI инкапсулирует объекты с помощью хэндлов, причём эта инкапсуляция получается намного сильнее, чем в типичной программе на C++. Мы не только ничего не знаем о внутреннем устройстве объектов, которые скрываются за хэндлами, — мы не знаем также их размер и местоположение.
мы не только не знаем о внутреннем устройстве HANDLE, мы вообще про него ничего не знаем. Если в мой метод передается HANDLE я не знаю можно ли к нему применить SetConsoleCursorPosition или WriteFile. Является ли такая возведенная в абсолют инкапсуляция признаком самого правильного ООП?
Здравствуйте, Odi$$ey, Вы писали:
OE>мы не только не знаем о внутреннем устройстве HANDLE, мы вообще про него ничего не знаем. Если в мой метод передается HANDLE я не знаю можно ли к нему применить SetConsoleCursorPosition или WriteFile. Является ли такая возведенная в абсолют инкапсуляция признаком самого правильного ООП?
Ну, во-первых, здесь никто не утверждал, что WinAPI — это "самое правильное ООП". Ошибки проектирования можно найти в любой системе.
По поводу HANDLE. У разработчиков WinAPI было два варианта:
— Ввести уникальный тип хэндла для каждого объекта ядра. Например, HFILE, HCONSOLE и т. д. Это позволило бы разрулить проблему, о которой ты говоришь. Зато при вызове функций, общих для всех типов объектов (CloseHandle, DuplicateHandle, WaitForSingleObject и т. д.) потребовалось бы явное приведение типа.
— Оставить один общий тип для всех хэндлов. При этом "лишние" приведения типа не требуются, но теоретически может возникнуть неоднозначность.
Разработчики из МС выбрали второй путь. Лично я ни разу не испытывал проблем всвязи с этим, поэтому я считаю, что это было правильное решение. Но даже если был бы выбран первый вариант (нам ничего не мешает хоть сейчас взять и подправить соответствующий апишный хедер), это никак не изменило бы дизайн WinAPI. Для наглядности рассмотрим такой пример:
Так вот, я не считаю, что благодаря паре лишних приведений типа первый вариант сразу стал более объектно-ориентированным. ООП вообще не занимается мелкими синтаксическими заморочками — он нужен для решения архитектурных проблем. В данном конкретном случае, благодаря полиморфному поведению объектов ядра есть принципиальная возможность ждать на любом их наборе. Если бы объекты ядра не допускали такой возможности, реализовать аналогичную функциональность было бы значительно сложнее.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
AS>Так вот, я не считаю, что благодаря паре лишних приведений типа первый вариант сразу стал более объектно-ориентированным. ООП вообще не занимается мелкими синтаксическими заморочками — он нужен для решения архитектурных проблем. В данном конкретном случае, благодаря полиморфному поведению объектов ядра есть принципиальная возможность ждать на любом их наборе. Если бы объекты ядра не допускали такой возможности, реализовать аналогичную функциональность было бы значительно сложнее.
Зато пойди догадайся, не смотря в документацию, что значит твой WaitForMultipleObjects относительно hThread. Это Join или это Abort?
А может до тебя работал веселый программист, который так назвал хэндл файла?
HANDLE — это что-то из динамического программирования. Когда тип объекта проверяется только в рантайме.
Все равно, что в C# все параметры функций делать с типом object.
Пусть там внутри происходит приведение типов и InvalidCast в случае чего валится.
Это усложняет и удорожает разработку и поддержку и снижает качество готового продукта.
Не зря же вокруг всех этих хэндлов со временем стали появляться обертки в виде классов.
Здравствуйте, MatFiz, Вы писали:
MF>HANDLE — это что-то из динамического программирования. Когда тип объекта проверяется только в рантайме.
Динамическое программирование это раздел науки "Методы оптимизации". А классификация динамическая/статическая типизация ортогональна классификации ООП/не ООП.
MF>Все равно, что в C# все параметры функций делать с типом object. MF>Пусть там внутри происходит приведение типов и InvalidCast в случае чего валится.
Валидность хэндла надо проверять в любом случае.
MF>Это усложняет и удорожает разработку и поддержку и снижает качество готового продукта.
А использовании WinAPI вообще усложняет и удорожает разработку =). Только там проблемы посеръезней чем типизация хэндлов.
MF>Не зря же вокруг всех этих хэндлов со временем стали появляться обертки в виде классов.
Обертки стали делать в первую очередь чтобы автоматичекси закрывать хэндлы.
Здравствуйте, Alexander Shargin, Вы писали:
AS>Здравствуйте, Cyberax, Вы писали:
C>>Отменили. Так как не один ты такой умный и SetWindowLong (кстати, правильно использовать SetWindowLongPtr) некоторые пакеты уже использовали для разных нужд. В результате, в ATL добавили хак с динамической кодогенерацией.
AS>Хак с динамической кодогенерацией добавили, потому что это наиболее эффективный способ. Но это не значит, что других способов решить проблему не существует. Например, можно использовать SetProp для назначения окну именованного свойства.
Кроме SetProp есть еще один способ. При создании класса окна поле cbWndExtra структуры WNDCLASS(EX) указывает, сколько байт размещать дополнительно при создании нового окна.
Здравствуйте, Сергей, Вы писали:
С>Кроме SetProp есть еще один способ. При создании класса окна поле cbWndExtra структуры WNDCLASS(EX) указывает, сколько байт размещать дополнительно при создании нового окна.
Это понятно, но это не универсальный способ — если сабклассишь уже существующий контрол, ты никак не можешь увеличить количество байт, связанных с ним. Именно поэтому данный метод не используют в универсальных фреймворках.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Здравствуйте, VladD2, Вы писали:
VD>Даже посылка сообщений кое где присутствует .
Даже открытие файла — на самом деле посылка сообщения (I/O request packet) объекту устройства.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, Odi$$ey, Вы писали:
OE>мы не только не знаем о внутреннем устройстве HANDLE, мы вообще про него ничего не знаем. Если в мой метод передается HANDLE я не знаю можно ли к нему применить SetConsoleCursorPosition или WriteFile.
А в jscript, например, вообще нет возможности определить тип параметра для метода, соответственно вообще никогда непонятно, что туда будет передано. И ничего, живут люди, и даже ООП используют.
OE>Является ли такая возведенная в абсолют инкапсуляция признаком самого правильного ООП?
Вроде пока еще никто не утверждал, что это именно "самый правильный" ООП..?
AS>Это понятно, но это не универсальный способ — если сабклассишь уже существующий контрол, AS>ты никак не можешь увеличить количество байт, связанных с ним.
Подозреваю что в C++ тоже непросто для уже существующего объекта добавить несколько новых полей.
Здравствуйте, Arioch, Вы писали:
AS>>Это понятно, но это не универсальный способ — если сабклассишь уже существующий контрол, AS>>ты никак не можешь увеличить количество байт, связанных с ним.
A>Подозреваю что в C++ тоже непросто для уже существующего объекта добавить несколько новых полей.
Если проводить аналогию subclassing — наследование, то всё решаемо в C++.
Здравствуйте, MatFiz, Вы писали:
MF>Это усложняет и удорожает разработку и поддержку и снижает качество готового продукта. MF>Не зря же вокруг всех этих хэндлов со временем стали появляться обертки в виде классов.
Ага. Лично мне было легче писать на WinAPI, чем с использованием MFC... так что что это за обёртки, тоже ещё надо посмотреть
AS>Так вот, я не считаю, что благодаря паре лишних приведений типа первый вариант сразу стал более объектно-ориентированным.
Замечу мимоходом, что и первый вариант в Win API есть. Только в другом месте. HBITMAP, HPEN, HBRUSH etc. vs. HGDIOBJECT. И приведение типа порой приходится делать — та же SelectObject возвращает HGDIOBJECT
Здравствуйте, Alexander Shargin, Вы писали:
AS>WinAPI инкапсулирует объекты с помощью хэндлов, причём эта инкапсуляция получается намного сильнее, чем в типичной программе на C++. Мы не только ничего не знаем о внутреннем устройстве объектов, которые скрываются за хэндлами, — мы не знаем также их размер и местоположение.
То же самое было в MS-DOS. Правда, тип хендлов только один — файловые. Следует ли из этого, что MS-DOS — тоже ООП ?
>Объекты, с которыми мы работаем на уровне WinAPI, очень тяжело "испортить", перезаписав их память, вызвав для них неправильный метод и т. п.
Вот это для DOS неверно, но причины тут очень далекие от ООП.
По сути дела, единственный способ сделать что-либо с объектом — это использовать связанный с ним API, то есть его интерфейс. Таким образом, в WinAPI очень чётко прослеживается разделение интерфейса (API) и реализации — это и есть инкапсуляция.
Здравствуйте, VladD2, Вы писали:
VD>Примеры, плиз, в студию. Я лично вижу другие примеры. API Виндвос и Линукс имеют выраженную ООП архитектуру.
Смешно. Как дети малые. И не надоело вам драться этими деревянными мечами? ООП — не ООП — это что, вопрос вероисповедания? Фактически, все так называемое ООП в API сводится к одной простой проблеме — передается ли там явный "this" или используются внутренние статические переменные. Вот и вся разница. Таким образом, fopen — это ООП, а strtok — нет. Если есть "this" и обратные вызовы с этим "this", есть и наследование и много других нехороших слов. И вообще, и в WinAPI т в POSIX есть и ООП и не-ООП функции. Имеется так же много функций, которым "this" не нужен вообще. Ну что-ж, это просто статические функции класса, не более того. Вот и все ООП.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, McSeem2, Вы писали: MS>Смешно. Как дети малые. И не надоело вам драться этими деревянными мечами? ООП — не ООП — это что, вопрос вероисповедания?
Максим, это не вопрос вероисповедания. Это вопрос понимания того, что такое ООП. Умение увидеть ООП там, где нет надписи "ООП здесь" достаточно важно для разработчика софта. Эта дискуссия явно показывает, что большинство народу до сих пор не понимает, что такое ООП. Поэтому мы должны и будем вести просветительскую работу, вытягивая серую массу из трясины невежества.
fopen — ООП в некотором, очень ограниченном смысле: есть объект FILE, у которого есть идентити (его адрес) некоторое состояние, изменяемое при взаимодействии с другими объектами. На практике, это не более чем процедурное программирование: есть структура данных, и есть набор процедур, которые с ней оперируют.
Вот типичный пример определения этой структуры:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
В отличие от ООП, структура прозрачна, и позволяет добавлять неопределенное количество взаимодействующих с ней процедур. Т.е. не удается разумным образом определить поведение объекта, а это необходимо для того, чтобы рассуждать в терминах ООП. Даже модульностью здесь не пахнет — как сама структура, так и связанные с ней процедуры живут в глобальном плоском пространстве имен.
Вот СreateFile — уже ООП, потому что появились инкапсуляция и полиморфизм.
strtok — вообще ошибка природы. Она нарушает все известные парадигмы, и не укладывается ни в функциональное, ни в объектно-ориентированное, ни в процедурное программирование. Ее можно только порекомендовать как пример антипаттерна.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, McSeem2, Вы писали: MS>>Смешно. Как дети малые. И не надоело вам драться этими деревянными мечами? ООП — не ООП — это что, вопрос вероисповедания? S>Максим, это не вопрос вероисповедания. Это вопрос понимания того, что такое ООП. Умение увидеть ООП там, где нет надписи "ООП здесь" достаточно важно для разработчика софта. Эта дискуссия явно показывает, что большинство народу до сих пор не понимает, что такое ООП. Поэтому мы должны и будем вести просветительскую работу, вытягивая серую массу из трясины невежества.
ИМХО, в этой дискуссии точнее было бы употреблять термин ОО дизайн, а не ООП. Язык С всё-таки не ООЯ, поэтому клиент сам вынужден следить за тем, чтобы поведение и состояние не разбежались по разным углам.
C>>Отменили. Так как не один ты такой умный и SetWindowLong (кстати, правильно использовать SetWindowLongPtr) некоторые пакеты уже использовали для разных нужд. В результате, в ATL добавили хак с динамической кодогенерацией.
AS>Хак с динамической кодогенерацией добавили, потому что это наиболее эффективный способ. Но это не значит, что других способов решить проблему не существует. Например, можно использовать SetProp для назначения окну именованного свойства.
Это корявое решение — оно не позволяет перехватить WM_CREATE и все сообщения которые приходят до него. Для того чтобы перехватить WM_CREATE в таком подходе делают так — перед вызовом CreateWindow кладут указатель в TLS, а потом в оконной процедуре смотрят — если указателя нет в SetWindowLong поле — то берут его из TLS. Короче, кривизна страшная.
Здравствуйте, Sinclair, Вы писали:
S>Вот СreateFile — уже ООП, потому что появились инкапсуляция и полиморфизм.
Как говорит thesz, "а вот создатель ООП понимал термин по другому". Проблема, мне кажется, именно в размытости этого термина, поэтому ООП (как и монады ) можно увидеть везде. Но термин "монады" по крайней мере формализован, что же такое ООП — не знает никто. Пардон, понимает его по своему
S>struct _iobuf {
S> char *_ptr;
S> int _cnt;
S> char *_base;
S> int _flag;
S> int _file;
S> int _charbuf;
S> int _bufsiz;
S> char *_tmpfname;
S> };
S>typedef struct _iobuf FILE;
S>
S>В отличие от ООП, структура прозрачна, и позволяет добавлять неопределенное количество взаимодействующих с ней процедур.
Ты ошибаешься. Структура FILE непрозначна. Точнее, в некоторых реализациях она может быть обыччной struct, но все равно, надо к ней относиться как к непрозрачной.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Alexander Shargin, Вы писали:
AS>>WinAPI инкапсулирует объекты с помощью хэндлов, причём эта инкапсуляция получается намного сильнее, чем в типичной программе на C++. Мы не только ничего не знаем о внутреннем устройстве объектов, которые скрываются за хэндлами, — мы не знаем также их размер и местоположение.
PD>То же самое было в MS-DOS. Правда, тип хендлов только один — файловые. Следует ли из этого, что MS-DOS — тоже ООП ?
Из этого следует, что дизайн системы файлового ввода-вывода был построен по концепции, близкой к ООП. Действительно, ведь у хэндла были свои подфункции 21-ого прерывания и почему бы их не назвать методами?
Здравствуйте, FDSC, Вы писали:
FDS>Из этого следует, что дизайн системы файлового ввода-вывода был построен по концепции, близкой к ООП. Действительно, ведь у хэндла были свои подфункции 21-ого прерывания и почему бы их не назвать методами?
Ага, а функции работы с матрицами — методами матриц, с числами — методами чисел (например sin, cos) и т.д.
Здравствуйте, Left2, Вы писали:
L>Это корявое решение — оно не позволяет перехватить WM_CREATE и все сообщения которые приходят до него. Для того чтобы перехватить WM_CREATE в таком подходе делают так — перед вызовом CreateWindow кладут указатель в TLS, а потом в оконной процедуре смотрят — если указателя нет в SetWindowLong поле — то берут его из TLS. Короче, кривизна страшная.
Указатель в TLS сам по себе ничем не поможет отцу русской демократии. Для своего собственного окна он не нужен (можно передать адрес через lParam), а оконная процедура стандартного контрола (например, EDIT) ничего о нём не знает. Чтобы действительно перехватить WM_CREATE и иже с ним (если это действительно нужно), применяют хуки, либо регистрируют на основе класса контрола вспомогательный класс со специальной оконной процедурой StartWndProc. Затем, в обработчике WM_CREATE, происходит привязывание хэндла к указателю на объект (взятый из TLS). Сделать это можно различными способами — создать переходник, записать нужный адрес через SetProp и т. д. Таким образом, твоё дополнение никак не противоречит моему исходному посту — мы просто говорим о разных этапах сабклассинга окна.
Кстати, на практике реальная необходимость перехватить WM_CREATE возникает редко. Обычно все те же действия можно проделать и для уже существующего окна. Например, MFC предоставляет для этого специальную виртуальную функцию PreSubclassWindow.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
А вот это весьма спорно. В данном случае "сообщения посылаются" еще в 2 регистра.
Не говоря о командах вроде:
call [eax]
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, McSeem2, Вы писали: MS>Ты ошибаешься. Структура FILE непрозначна. Точнее, в некоторых реализациях она может быть обыччной struct, но все равно, надо к ней относиться как к непрозрачной.
К ней нельзя относиться как к непрозрачной. Потому, что она всё-таки прозрачна. Это как "не думать о белой обезьяне": как же я могу о ней не думать, если структура у меня видна, как на ладони? Она во всех реализациях — обычная struct.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
AS>Для своего собственного окна он не нужен (можно передать адрес через lParam),
Ну ладно — насчёт WM_CREATE согласен, но сообщения которые приходят ДО него уже таким образом не перехватишь
AS>а оконная процедура стандартного контрола (например, EDIT) ничего о нём не знает. Чтобы действительно перехватить WM_CREATE и иже с ним (если это действительно нужно), применяют хуки, либо регистрируют на основе класса контрола вспомогательный класс со специальной оконной процедурой StartWndProc. Затем, в обработчике WM_CREATE, происходит привязывание хэндла к указателю на объект (взятый из TLS). Сделать это можно различными способами — создать переходник, записать нужный адрес через SetProp и т. д. Таким образом, твоё дополнение никак не противоречит моему исходному посту — мы просто говорим о разных этапах сабклассинга окна.
Да я в целом не о том хотел сказать Хотел сказать что наличие такой уймы таких изощрённых способов для решения довольно простой задачи как нельзя лучше говорит именно о кривизне изначального дизайна
Здравствуйте, Left2, Вы писали:
L>Да я в целом не о том хотел сказать Хотел сказать что наличие такой уймы таких изощрённых способов для решения довольно простой задачи как нельзя лучше говорит именно о кривизне изначального дизайна
Кривизна возникает потому, что мы пытаемся скрестить две плохо совместимые объектные модели — модель C++ и модель Win32. Модель Win32 (в отличие от COM) проектировалась ещё до C++, и не была рассчитана на прямую совместимость с ним. Отсюда проблемы, но они достаточно локальны и давно прикрыты библиотеками (ATL). Поэтому делать на основе этого далеко идущие выводы я бы не стал.
Впрочем, я в этом топике не защищал и не собираюсь защищать Win32. Проблем у него хватает. Только с ООП эти проблемы мало связаны — ошибки дизайна возможны при любом подходе к проектированию.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
AS>Кривизна возникает потому, что мы пытаемся скрестить две плохо совместимые объектные модели — модель C++ и модель Win32. Модель Win32 (в отличие от COM) проектировалась ещё до C++, и не была рассчитана на прямую совместимость с ним. Отсюда проблемы, но они достаточно локальны и давно прикрыты библиотеками (ATL). Поэтому делать на основе этого далеко идущие выводы я бы не стал.
С этим не согласен. Предположим, Win32 API проектировался для C. Но ведь та же самая проблема (с передачей контекста в оконную процедуру) в терминах C тоже не решается!
AS>Впрочем, я в этом топике не защищал и не собираюсь защищать Win32. Проблем у него хватает. Только с ООП эти проблемы мало связаны — ошибки дизайна возможны при любом подходе к проектированию.
Здравствуйте, Left2, Вы писали:
L>С этим не согласен. Предположим, Win32 API проектировался для C. Но ведь та же самая проблема (с передачей контекста в оконную процедуру) в терминах C тоже не решается!
Гм... Наверное, я что-то упустил. Давай ещё раз:
1. Окно наше собственное. Добавляем нужное количество байт в window data при регистрации класса. Туда кладём контекст.
2. Окно не наше. При сабклассинге записываем указатель на структуру с нужными данными с помощью SetProp.
3. Окно не наше + нам нужно получить все без исключения сообщения. Создаём суперкласс на основе исходного класса. Получаем все сообщения в нашей собственной оконной процедуре, из которой дёргаем исходную. При регистрации суперкласса можно заодно добавить места в window data, где можно будет разместить дополнительные данные, необходимые для нашей программы.
На первый взгляд это выглядит сложно и не логично. Но если задуматься над этим, всё укладывается в чёткую схему.
— В варианте 3 мы создаём статический класс, порождённый от существующего. Это в чистом виде аналог С++, где мы наследуемся от класса, добавляем новые поля и переопределяем некоторые методы.
— В варианте 2 мы изменяем класс существующего окна динамически (во время выполнения). Это совершнно другая функциональность, для которой нет прямого аналога в С++.
— Наконец, вариант 1 — просто частный случай варианта 3.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
L>>С этим не согласен. Предположим, Win32 API проектировался для C. Но ведь та же самая проблема (с передачей контекста в оконную процедуру) в терминах C тоже не решается!
AS>Гм... Наверное, я что-то упустил. Давай ещё раз: AS>1. Окно наше собственное. Добавляем нужное количество байт в window data при регистрации класса. Туда кладём контекст. AS>2. Окно не наше. При сабклассинге записываем указатель на структуру с нужными данными с помощью SetProp. AS>3. Окно не наше + нам нужно получить все без исключения сообщения. Создаём суперкласс на основе исходного класса. Получаем все сообщения в нашей собственной оконной процедуре, из которой дёргаем исходную. При регистрации суперкласса можно заодно добавить места в window data, где можно будет разместить дополнительные данные, необходимые для нашей программы.
AS>На первый взгляд это выглядит сложно и не логично. Но если задуматься над этим, всё укладывается в чёткую схему. AS>- В варианте 3 мы создаём статический класс, порождённый от существующего. Это в чистом виде аналог С++, где мы наследуемся от класса, добавляем новые поля и переопределяем некоторые методы. AS>- В варианте 2 мы изменяем класс существующего окна динамически (во время выполнения). Это совершнно другая функциональность, для которой нет прямого аналога в С++. AS>- Наконец, вариант 1 — просто частный случай варианта 3.
Ну НЕ ПРОСТО это Никак не просто что мешало, к примеру, в оконную процедуру передавать не 4 параметра а 1 — указатель на структуру. А в эту структуру впихнуть контекст. Вот это — простое решение — и работает и для С и для С++. Контекст нужен практически в любом окне, а там где он не нужен — он никому не мешает.
Вот тебе пример насчёт дизайна, который ложится на один язык и не ложится на другой — это IXMLHTTPRequest::onreadystatechange. Для того чтобы создать callback-процедуру на С++ — нужно написать 2-3 десятка строчек даже с применением библиотек типа ATL. А вот на javasrcipt — тут вообще нЕчего делать — пишешь oRequest.onreadystatechange = function() { DoSomething() }. Вот тут действительно — разные языки ложатся на этот дизайн с разным геморроем.
А в том что ты описал — я не вижу чтобы такая изощрённость логично ложилась бы хоть на какой-нить язык — хоть на С, хоть на С++. Типичная кривизна дизайна, ИМХО — наверняка пришедшая из какого-нить дремучего проекта, 100 лет назад сделанного главным архитектором WinAPI
Здравствуйте, Left2, Вы писали:
L>>>С этим не согласен. Предположим, Win32 API проектировался для C. Но ведь та же самая проблема (с передачей контекста в оконную процедуру) в терминах C тоже не решается!
[skip]
L>Ну НЕ ПРОСТО это Никак не просто
Так непросто или невозможно? Мне показалось, что ты утверждаешь второе. Наверно, не так тебя понял...
>что мешало, к примеру, в оконную процедуру передавать не 4 параметра а 1 — указатель на структуру. А в эту структуру впихнуть контекст. Вот это — простое решение — и работает и для С и для С++. Контекст нужен практически в любом окне, а там где он не нужен — он никому не мешает.
Если хочешь обсудить альтернативный дизайн, опиши конкретнее, как это всё будет выглядеть в тех случаях, что я рассмотрел в предыдущем сообщении. А то не очень понятно, о чём речь идёт.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, FDSC, Вы писали:
FDS>>Из этого следует, что дизайн системы файлового ввода-вывода был построен по концепции, близкой к ООП. Действительно, ведь у хэндла были свои подфункции 21-ого прерывания и почему бы их не назвать методами?
К>Ага, а функции работы с матрицами — методами матриц, с числами — методами чисел (например sin, cos) и т.д.
Смотря как они реализованы. Или ты считаешь, что если объект представляет матрицу, то это уже не объект???
Здравствуйте, FDSC, Вы писали:
FDS>Здравствуйте, Курилка, Вы писали:
К>>Ага, а функции работы с матрицами — методами матриц, с числами — методами чисел (например sin, cos) и т.д.
FDS>Смотря как они реализованы. Или ты считаешь, что если объект представляет матрицу, то это уже не объект???
Ну да, если у тебя в руках молоток...
Просто надо осторожней с фанатизмом, каждому инструменту своё применение
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, McSeem2, Вы писали: MS>>Ты ошибаешься. Структура FILE непрозначна. Точнее, в некоторых реализациях она может быть обыччной struct, но все равно, надо к ней относиться как к непрозрачной. S>К ней нельзя относиться как к непрозрачной. Потому, что она всё-таки прозрачна. Это как "не думать о белой обезьяне": как же я могу о ней не думать, если структура у меня видна, как на ладони? Она во всех реализациях — обычная struct.
Если структура FILE стандартизована, и одинакова во всех реализациях — тогда она прозрачна. А если нет — то нет. И неважно, можно к ней добраться, или нельзя. Также как и недокументированные функции API — ты можешь их использовать, но этого делать нельзя — они не являются частью стандартизованного public интерфейса, и могут в следующей версии вообще уйти. И не важно, пусть даже эта недокументированная функция сейчас присутствует во всех реализациях.
Я к приватным данным твоего класса тоже пролезу без проблем, кстати, если захочу. #define private public, #include "you_private_class" — и вперед. Вывод? Да С++ говно язык, не ООП ни разу, никакой инкапсуляции не обеспечивает . Как я могу думать об инкапсуляции, если они, privat-ы, у меня как на ладони?
L>>Ну НЕ ПРОСТО это Никак не просто AS>Так непросто или невозможно? Мне показалось, что ты утверждаешь второе. Наверно, не так тебя понял...
Конечно же возможно Но делается это как бы так сказать — per rectum, извините за латынь... Я всего лишь забыл добавить слово "просто" в конце предложения о том что "не решается", я сам виноват — криво выразился .
>>что мешало, к примеру, в оконную процедуру передавать не 4 параметра а 1 — указатель на структуру. А в эту структуру впихнуть контекст. Вот это — простое решение — и работает и для С и для С++. Контекст нужен практически в любом окне, а там где он не нужен — он никому не мешает. AS>Если хочешь обсудить альтернативный дизайн, опиши конкретнее, как это всё будет выглядеть в тех случаях, что я рассмотрел в предыдущем сообщении. А то не очень понятно, о чём речь идёт.
Ну как один из вариантов — в функцию CreateWindow передаётся lparam, который потом приходит в оконную процедуру для ВСЕХ сообщений. Неважно, отдельным ли параметром или в виде одного из полей структуры, в которую сведены все параметры оконной процедуры.
Ещё один вариант — в функцию CreateWindow передаётся lparam который АВТОМАТИЧЕСКИ ставится в специальное WindowProperty ДО прихода каких-либо сообщений.
Здравствуйте, Left2, Вы писали:
L>Ну как один из вариантов — в функцию CreateWindow передаётся lparam, который потом приходит в оконную процедуру для ВСЕХ сообщений. Неважно, отдельным ли параметром или в виде одного из полей структуры, в которую сведены все параметры оконной процедуры.
Информация, которая передаётся в CreateWindow — это по сути дела то, что передаётся конструктору объекта окна. Поэтому она и доступна только в обработчике WM_(NC)CREATE. А дальше ты либо запоминаешь её во внутренних переменных объекта окна (то есть в window data), либо как-то используешь для инициализации и забываешь про неё. Передавать одно и то же постоянно как параметр — это просто лишние тормоза без видимых на то причин. Такие данные должны храниться внутри объекта окна.
А в случае сабклассинга lparam в CreateWindow уже кто-то передал до тебя, и тебе он вообще никак не поможет — всё равно придётся обратиться к SetProp. Где счастье?
L>Ещё один вариант — в функцию CreateWindow передаётся lparam который АВТОМАТИЧЕСКИ ставится в специальное WindowProperty ДО прихода каких-либо сообщений.
L>>Ну как один из вариантов — в функцию CreateWindow передаётся lparam, который потом приходит в оконную процедуру для ВСЕХ сообщений. Неважно, отдельным ли параметром или в виде одного из полей структуры, в которую сведены все параметры оконной процедуры.
AS>Информация, которая передаётся в CreateWindow — это по сути дела то, что передаётся конструктору объекта окна. Поэтому она и доступна только в обработчике WM_(NC)CREATE. А дальше ты либо запоминаешь её во внутренних переменных объекта окна (то есть в window data), либо как-то используешь для инициализации и забываешь про неё. Передавать одно и то же постоянно как параметр — это просто лишние тормоза без видимых на то причин. Такие данные должны храниться внутри объекта окна.
Тут получается что мне нужно пропихивать сначала LPARAM в WM_CREATE, а потом его как-то ещё куда-то сохранять. А зачем? Мне всего-то надо иметь сразу ассоциированый с окном контекст и ВСЁ — это перекрывает все мои use cases.
Ну и про тормоза не нужно Всё-таки пропихнуть ещё один 4-х (8-ми) байтный параметр в оконную процедуру — этого вообще никто не заметит
AS>А в случае сабклассинга lparam в CreateWindow уже кто-то передал до тебя, и тебе он вообще никак не поможет — всё равно придётся обратиться к SetProp. Где счастье?
L>>Ещё один вариант — в функцию CreateWindow передаётся lparam который АВТОМАТИЧЕСКИ ставится в специальное WindowProperty ДО прихода каких-либо сообщений.
AS>ОК. Сейчас в Win32 мы имеем:
... код поскипан ...
AS>Что-то я не уловил принципиальной разницы.
Тем не менее ИМХО она есть:
1. Я могу без проблем обработать сообщения, которые приходят ДО WM_CREATE. Контекст у меня будет всегда, а не только начиная с определённого момента.
2. Если мне нужно обрабатывать WM_CREATE — то я могу его и не обрабатывать, не плодя код без необходимости.
Здравствуйте, Left2, Вы писали:
L>Тут получается что мне нужно пропихивать сначала LPARAM в WM_CREATE, а потом его как-то ещё куда-то сохранять. А зачем? Мне всего-то надо иметь сразу ассоциированый с окном контекст и ВСЁ — это перекрывает все мои use cases.
Хех. Скажи пожалуйста, зачем люди пишут:
class CMyClass
{
private:
int m_nParam;
public:
CMyClass(int nParam) : m_nParam(nParam) {}
};
...
CMyClass my(1234);
вместо того чтобы передавать 1234 во все методы объекта my?
Если развить твою мысль, нужно было ввести в стандарт С++ пункт, что компилятор должен где-то сохранять параметр, передаваемый в конструктор, и затем передавать его во все методы. Ведь это позволило бы тебе сэкономить целую строчку на написание конструктора! И это покрыло бы все твои use cases!
AS>>Что-то я не уловил принципиальной разницы.
L>Тем не менее ИМХО она есть: L>1. Я могу без проблем обработать сообщения, которые приходят ДО WM_CREATE. Контекст у меня будет всегда, а не только начиная с определённого момента.
А можно огласить весь список "сообщений, которые приходят ДО WM_CREATE"? WM_NCCREATE — это самое первое сообщение, которое получает окно. В своём примере я специально подчеркнул, что create param в обработчике этого сообщения доступен.
L>2. Если мне нужно обрабатывать WM_CREATE — то я могу его и не обрабатывать, не плодя код без необходимости.
Угу, и конструкторы в С++ можно не писать, не плодя код без необходимости. См. выше.
В мире Win32 WM_CREATE — это твой конструктор. А WM_DESTROY — деструктор. И относиться к ним нужно соответственно. Твоё нежелание их писать не имеет ничего общего с хорошим или плохим дизайном Win32.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Здравствуйте, FDSC, Вы писали:
К>>Ага, а функции работы с матрицами — методами матриц, с числами — методами чисел (например sin, cos) и т.д.
FDS>Смотря как они реализованы. Или ты считаешь, что если объект представляет матрицу, то это уже не объект???
Нет, не объект. Всё-таки даже в не всё должно быть объектом. Например, числа никогда объектами не являются. Если мы объявляем переменную типа int, то мы потом можем сколько угодно раз изменять её. Но мы не можем, присовив этой переменной, скажем, единицу, изменить саму единицу. Единица в данном случае — нечто целое и неделимое.
Думаю, ООП работает не только с объектами, но и со "значениями". Значениям нельзя посылать сообщения, их внутренняя структура неизменна, у них по-другому определятеся identity. Значения могут передаваться в сообщениях. Как представлять данную сущность — через значение или через объект — решается на основе опыта.
Приведу пример с теми же матрицами. Если матрицу сделать объектом, то матрица должна быть изменяемой. Т.е. должны быть такие сообщения, которые изменяют отдельные компоненты. При этом разумно к объекту "матрица" прикрутить события. Иначе, если мы присвоим матрицу 4-го порядка чему-нибудь вроде RenderingDevice, а потом станем изменять её компоненты, то это никак не затронет картинку, воспроизводимую RenderingDevice. Кроме того, уже не будет объекта IdentityMatrix типа Matrix, поскольку его можно будет изменить и это будет уже не IdentityMatrix. Вместо этого нужно будет иметь singletone-объект IdentityMatrixMaker, который будет посылать данной матрице такую серию сообщению, которая сделает её единичной.
Если же рассматривать матрицу как значения типа Matrix, то указанные проблемы отпадают. Правда, появляется проблема с тем, что Matrix — неизменяемое значение. Но это легко исправить, введя объект типа MatrixBuilder.
AS>Если развить твою мысль, нужно было ввести в стандарт С++ пункт, что компилятор должен где-то сохранять параметр, передаваемый в конструктор, и затем передавать его во все методы. Ведь это позволило бы тебе сэкономить целую строчку на написание конструктора! И это покрыло бы все твои use cases!
Не надо развивать мою мысль подобным образом, это уже утрирование получается Скажу так — лично я инкапсулирую переменные только примерно в 25% классов — которые торчат наружу дизайна. И всё! А писать конструктор в КАЖДОМ классе, даже если он просто связывает две-три сущности, да ещё и обьявлен внутри функции или cpp-файла — это конечно концептуально, но лично я не хочу делать лишнюю работу только ради концептуальности.
AS>Угу, и конструкторы в С++ можно не писать, не плодя код без необходимости. См. выше.
Именно!
AS>В мире Win32 WM_CREATE — это твой конструктор. А WM_DESTROY — деструктор. И относиться к ним нужно соответственно. Твоё нежелание их писать ничего общего не имеет с хорошим или плохим дизайном Win32.
Скажем так — в С++ я МОГУ не писать конструктор когда он мне не нужен. И если бы компилятор С++ требовал бы наличия конструктора у КАЖДОГО класса — программисты бы взвыли. И называли бы это кривизной дизайна. И я бы взвыл первым В конце концов — и компиляторы, и API пишутся для программистов. А программисты — это люди. И им должно быть удобно. А если им неудобно — это кривой дизайн.
Ещё раз попробую перефразировать — если для решения ТИПОВОЙ задачи мне нужно написать КУЧУ кода — то дизайн кривой. Особенно хорош в этом плане Symbian. Вроде бы в нём всё OOP — никаких тебе свободных функций, одни классы. Но когда начинаешь решать типовые задачи и видишь что для этого тебе надо написать десяток классов — то извините, это API кривое. Мне не нужны шашечки, мне бы ехать
Здравствуйте, Gaperton, Вы писали: G>Если структура FILE стандартизована, и одинакова во всех реализациях — тогда она прозрачна. А если нет — то нет. И неважно, можно к ней добраться, или нельзя. Также как и недокументированные функции API — ты можешь их использовать, но этого делать нельзя — они не являются частью стандартизованного public интерфейса, и могут в следующей версии вообще уйти. И не важно, пусть даже эта недокументированная функция сейчас присутствует во всех реализациях.
Недокументированность функций имеет слабое отношение к теме вопроса. Речь о том, что handle — это не указатель на структуру, а некоторый селектор в неизвестно куда. И работать с ним можно исключительно путем вызова функций, пусть даже и недокументированных.
G>Я к приватным данным твоего класса тоже пролезу без проблем, кстати, если захочу. #define private public, #include "you_private_class" — и вперед. Вывод? Да С++ говно язык, не ООП ни разу, никакой инкапсуляции не обеспечивает . Как я могу думать об инкапсуляции, если они, privat-ы, у меня как на ладони?
Ну, по крайней мере, ты сделаешь это осознанно. А написать file->pos тебе поможет среда с автодополнением, и компилятор ничего плохого не скажет.
Ребята, может хватит детский сад разводить? Вам что, в школе не преподавали структурное программирование? Или вы его узнать не можете, даже посмотрев на него вплотную?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
K>Нет, не объект. Всё-таки даже в не всё должно быть объектом. Например, числа никогда объектами не являются.
Ничего подобного. С точки зрения практической реализации — да, числа объектами не являются.
Однако с точки зрения теории кристалла, никаких препятствий к тому, чтобы сделать числа объектами, нет.
Для этого достаточно сделать их immutable, и считать, что все четыре миллиарда значений int32 кем-то были созданы еще до начала работы программы.
В переменных хранятся ссылки на эти значения. Все операции с интами возвращают указатель на подходящий инт.
K>Если мы объявляем переменную типа int, то мы потом можем сколько угодно раз изменять её. Но мы не можем, присовив этой переменной, скажем, единицу, изменить саму единицу. Единица в данном случае — нечто целое и неделимое.
Да-да, единица — это некоторый объект класса Int32. Отличается от всех остальных объектов этого класса тем, что результат x.Multiply(1) для любого x будет по-прежнему равен x.
K>Приведу пример с теми же матрицами. Если матрицу сделать объектом, то матрица должна быть изменяемой.
Не обязательно. Запросто можно заставить матрицу быть неизменной. Если изменяем компонент — мы получаем новую матрицу.
K>Если же рассматривать матрицу как значения типа Matrix, то указанные проблемы отпадают. Правда, появляется проблема с тем, что Matrix — неизменяемое значение. Но это легко исправить, введя объект типа MatrixBuilder.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Sinclair wrote: > Для этого достаточно сделать их immutable, и считать, что все четыре > миллиарда значений int32 кем-то были созданы еще до начала работы > программы.
Кстати, примерно так и было сделано в Smalltalk.
Здравствуйте, Sinclair, Вы писали:
S>Ничего подобного. С точки зрения практической реализации — да, числа объектами не являются. S>Однако с точки зрения теории кристалла, никаких препятствий к тому, чтобы сделать числа объектами, нет. S>Для этого достаточно сделать их immutable, и считать, что все четыре миллиарда значений int32 кем-то были созданы еще до начала работы программы.
Кстати в Хаскелле они похожим образом трактуются. Тип Int — как длиннющее перечисление, а Integer — вообще бесконечное.
Здравствуйте, Sinclair, Вы писали:
K>>Нет, не объект. Всё-таки даже в не всё должно быть объектом. Например, числа никогда объектами не являются. S>Ничего подобного. С точки зрения практической реализации — да, числа объектами не являются. S>Однако с точки зрения теории кристалла, никаких препятствий к тому, чтобы сделать числа объектами, нет. S>Для этого достаточно сделать их immutable, и считать, что все четыре миллиарда значений int32 кем-то были созданы еще до начала работы программы. S>В переменных хранятся ссылки на эти значения. Все операции с интами возвращают указатель на подходящий инт.
Да, вот только САМ int мы не можем изменить. Мы не можем сказать 1.Increase() и потом получить истинное утверждение 1 == 2. Наконец, значения сравниваются не по ссылке, а по значению. Это позволяет нам относиться к матрице как просто к представителю некоторого уже существующего множества, а не к созданному из небытия объекту. Методы вроде BuildMatrix — это всего лишь посылка сообщению некоторому MatrixBuilder, который выбирает нужное значние из множества матрици возвращает его.
K>>Если мы объявляем переменную типа int, то мы потом можем сколько угодно раз изменять её. Но мы не можем, присовив этой переменной, скажем, единицу, изменить саму единицу. Единица в данном случае — нечто целое и неделимое. S>Да-да, единица — это некоторый объект класса Int32. Отличается от всех остальных объектов этого класса тем, что результат x.Multiply(1) для любого x будет по-прежнему равен x.
Да мы вообще никаких совйств единицы изменить не можем. Что ж, если кому-то не нравится моя терминология, то можно сказать так: существуют изменяемые и неизменяемые объекты. Изменяемые могут создаваться и уничтожаться, а так же мы можем изменять их внутреннюю структуру. Кроме того, два по-отдельности созданных изменяемых объекта никогда не могут быть равны. Неизменяемые объекты неявно существуют всегда, мы не можем их создать или уничожить, но мы можем выбрать нужные из множества.
K>>Приведу пример с теми же матрицами. Если матрицу сделать объектом, то матрица должна быть изменяемой. S>Не обязательно. Запросто можно заставить матрицу быть неизменной. Если изменяем компонент — мы получаем новую матрицу.
Нет, мы к матрице можем прикрутить метод, который по номеру строки и столбца а так же по некоторому значению возвращает новую матрицу, в которой в указанная компонента будет принимать новое значение. Т.е. будет взята матрица из множества всевозможных матриц, а не изменена структура имеющейся.
Здравствуйте, konsoletyper, Вы писали: K>Да, вот только САМ int мы не можем изменить. Мы не можем сказать 1.Increase() и потом получить истинное утверждение 1 == 2.
Я и не предлагал.
Просто результатом 1.Increase() будет ссылка на другой Int, и утверждение 1.Increase() == 2 будет истинным. K>Наконец, значения сравниваются не по ссылке, а по значению.
Совершенно необязательно. Если value-объекты неизменны, то нет никакой разницы, сравнивать их по значению или по ссылке. Все ссылки на двойку будут одинаковы просто потому, что сушествует ровно один экземпляр двойки.
K>Это позволяет нам относиться к матрице как просто к представителю некоторого уже существующего множества, а не к созданному из небытия объекту.
Совершенно верно. Создание из небытия — это уже реализация, экономящая память (очевидно, что хранение полного набора возможных матриц 4*4 является типичным примером преждевременной оптимизации). K>Методы вроде BuildMatrix — это всего лишь посылка сообщению некоторому MatrixBuilder, который выбирает нужное значние из множества матрици возвращает его.
K>Да мы вообще никаких совйств единицы изменить не можем. Что ж, если кому-то не нравится моя терминология, то можно сказать так: существуют изменяемые и неизменяемые объекты.
Совершенно верно. K> Изменяемые могут создаваться и уничтожаться, а так же мы можем изменять их внутреннюю структуру.
Уничтожение объектов нам, собственно говоря, не очень нужно. K>Кроме того, два по-отдельности созданных изменяемых объекта никогда не могут быть равны.
Ну, я бы сказал, не "равны", а "идентичны". K>Неизменяемые объекты неявно существуют всегда, мы не можем их создать или уничожить, но мы можем выбрать нужные из множества.
Можно и так считать. Поскольку они неизменяемые, то вопрос о том, существовали ли конкретные экземпляры до того, как мы их впервые использовали, является теологическим. Точно так же, как и вопрос о том, что происходит с объектами, на которые не остается ссылок.
S>>Не обязательно. Запросто можно заставить матрицу быть неизменной. Если изменяем компонент — мы получаем новую матрицу. K>Нет, мы к матрице можем прикрутить метод, который по номеру строки и столбца а так же по некоторому значению возвращает новую матрицу, в которой в указанная компонента будет принимать новое значение. Т.е. будет взята матрица из множества всевозможных матриц, а не изменена структура имеющейся.
Да.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
K>>Да, вот только САМ int мы не можем изменить. Мы не можем сказать 1.Increase() и потом получить истинное утверждение 1 == 2. S>Я и не предлагал. S>Просто результатом 1.Increase() будет ссылка на другой Int, и утверждение 1.Increase() == 2 будет истинным.
Ну, так 1.Increase() не поменяет структуру объекта 1. Просто это способ получить доступ к объекту 2 из множества целых чисел.
K>>Наконец, значения сравниваются не по ссылке, а по значению. S>Совершенно необязательно. Если value-объекты неизменны, то нет никакой разницы, сравнивать их по значению или по ссылке. Все ссылки на двойку будут одинаковы просто потому, что сушествует ровно один экземпляр двойки.
+1. Только обычно имеет место эмуляция такого поведения с соответствующим переопределением смысла отношения "равно".
K>>Это позволяет нам относиться к матрице как просто к представителю некоторого уже существующего множества, а не к созданному из небытия объекту. S>Совершенно верно. Создание из небытия — это уже реализация, экономящая память (очевидно, что хранение полного набора возможных матриц 4*4 является типичным примером преждевременной оптимизации).
Но вопрос лишь в том, как относиться к этому. Множество представимых в памяти компьютера матриц конечно. Мы можем выбрать элемент, тем или иным способом точно указав на него. Но т.к. память компьютера всех матриц не удержит, то мы эмулируем такое поведение переопределением отношения равенства для неизменяемых объектов и созданием "новых" матриц. С изменяемыми объектами всё по-другому — мы можем выбрать "какой-нибудь" объект из бесконечного множества, причём мы не можем точно указать на него до того, как он выбран.
Хочу ещё раз подчеркнуть, что вообще, да, всё есть объекты. Но мы на этих объектах эмылируем то, что я называю "значениями", или "неизменяемыми объектами", которые имеют несколько иное поведение.
K>>Методы вроде BuildMatrix — это всего лишь посылка сообщению некоторому MatrixBuilder, который выбирает нужное значние из множества матрици возвращает его.
K>>Да мы вообще никаких совйств единицы изменить не можем. Что ж, если кому-то не нравится моя терминология, то можно сказать так: существуют изменяемые и неизменяемые объекты. S>Совершенно верно.
Ну раз так, то можно и по другому переформулировать моё предположение: раз есть mutability, то это не значит, что стоит его использовать где попало. Более того, в конкретном случае с матрицами в большинстве случаев (например, для тех же 3D-рендереров) гораздо более грамотной является архитектура с immutable-матрицами, хотя, как говорится, it depends.
K>> Изменяемые могут создаваться и уничтожаться, а так же мы можем изменять их внутреннюю структуру. S>Уничтожение объектов нам, собственно говоря, не очень нужно.
Здравствуйте, konsoletyper, Вы писали:
K>Ну, так 1.Increase() не поменяет структуру объекта 1. Просто это способ получить доступ к объекту 2 из множества целых чисел.
Я с этим в очередной раз не спорю. ООП здесь в том, что именно объект 1 решает, какой объект вернуть в ответ на сообщение Increase. Другое дело, что его состояние никогда не меняется, и результат операции 1.Increase() (как, впрочем, и любой другой) всегда будет одним и тем же.
K>+1. Только обычно имеет место эмуляция такого поведения с соответствующим переопределением смысла отношения "равно".
С точки зрения теории кристалла это совершенно ненужная, а иногда и вредная оптимизация.
K>Но вопрос лишь в том, как относиться к этому. Множество представимых в памяти компьютера матриц конечно. Мы можем выбрать элемент, тем или иным способом точно указав на него. Но т.к. память компьютера всех матриц не удержит, то мы эмулируем такое поведение переопределением отношения равенства для неизменяемых объектов и созданием "новых" матриц.
Смешиваешь две несвязанные вещи. Создание новых матриц — это аналог "виртуальной" памяти. Т.е. потребителю всё равно кажется, что матрицы были там всегда.
Способ сравнения двух матриц на равенство никак с этим не связан. Генератор матриц всегда можно написать так, чтобы он никогда не создавал матрицу, если такая уже есть. В таком случае не будет риска получения двух неидентичных, но эквивалентных матриц. В противном случае генератор не является "прозначным": наличие в программе одновременно двух различных ссылок на одинаковые объекты противоречит наличию где-то склада готовых матриц, где каждая матрица представлена ровно один раз.
Замечу также, что генератор не обязан в течение всего времени жизни программы отдавать одну и ту же матрицу по одному и тому же адресу (иначе бы у него не хватило адресного пространства). Достаточно обеспечить все одновременно используемые матрицы различными адресами; те матрицы, которые больше не используются, могут быть безболезненно убиты и затем воссозданы уже с другим адресом. Это ничего не нарушит, т.к. чтобы обнаружить это, коду нужно сравить "новый" адрес со "старым", а для этого "старый" адрес должен был где-то храниться, а стало быть матрица не могла быть убита.
K>Хочу ещё раз подчеркнуть, что вообще, да, всё есть объекты. Но мы на этих объектах эмылируем то, что я называю "значениями", или "неизменяемыми объектами", которые имеют несколько иное поведение.
Видишь ли, это вопрос концептуальной чистоты. Либо мы специально вводим некие особые сущности — примитивные типы, как это делают Java и .Net, и усложняем модель, либо мы просто декларируем Immutable Object Pattern и говорим, что всё, что надо, эмулируется при помощи этого паттерна. В том числе и строки, и прочее.
Естественно, вопрос о применимости такого подхода в реальной жизни достаточно риторический. Даже если построить исполняющую среду, которая не будет сливать по производительности менее математизированным реализациям, то всё равно удобнее опираться на несколько более богатый набор примитивов out of the box.
K>Ну раз так, то можно и по другому переформулировать моё предположение: раз есть mutability, то это не значит, что стоит его использовать где попало. Более того, в конкретном случае с матрицами в большинстве случаев (например, для тех же 3D-рендереров) гораздо более грамотной является архитектура с immutable-матрицами, хотя, как говорится, it depends.
Совершенно верно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
K>>+1. Только обычно имеет место эмуляция такого поведения с соответствующим переопределением смысла отношения "равно". S>С точки зрения теории кристалла это совершенно ненужная, а иногда и вредная оптимизация.
А это что такое?
K>>Но вопрос лишь в том, как относиться к этому. Множество представимых в памяти компьютера матриц конечно. Мы можем выбрать элемент, тем или иным способом точно указав на него. Но т.к. память компьютера всех матриц не удержит, то мы эмулируем такое поведение переопределением отношения равенства для неизменяемых объектов и созданием "новых" матриц. S>Смешиваешь две несвязанные вещи. Создание новых матриц — это аналог "виртуальной" памяти. Т.е. потребителю всё равно кажется, что матрицы были там всегда.
Это я не смешиваю две вещи, а просто говорю об одном из способов эмулировать нужную сущность. Просто очень привык к подходу Java/.NET с переопределением Equals.
K>>Хочу ещё раз подчеркнуть, что вообще, да, всё есть объекты. Но мы на этих объектах эмылируем то, что я называю "значениями", или "неизменяемыми объектами", которые имеют несколько иное поведение. S>Видишь ли, это вопрос концептуальной чистоты. Либо мы специально вводим некие особые сущности — примитивные типы, как это делают Java и .Net, и усложняем модель, либо мы просто декларируем Immutable Object Pattern и говорим, что всё, что надо, эмулируется при помощи этого паттерна. В том числе и строки, и прочее.
Правильно, можно сам язык и рантайм (если таковой имеется) основать на нескольких простейшимх вещах. Но это никак не должно мешать нам о некоторых вещах думать немного-по другому. Более того, это не должно принципиально запрещать эмуляцию таких вещей. Но всё же лучше, если язык имеет немного сахару, автоматизирующего использование паттернов, а рантайм имеет "сахар", позволяющий получить оптимальный код.
Здравствуйте, Alexander Shargin, Вы писали:
AS>По поводу HANDLE. У разработчиков WinAPI было два варианта: AS>- Ввести уникальный тип хэндла для каждого объекта ядра. Например, HFILE, HCONSOLE и т. д. Это позволило бы разрулить проблему, о которой ты говоришь. Зато при вызове функций, общих для всех типов объектов (CloseHandle, DuplicateHandle, WaitForSingleObject и т. д.) потребовалось бы явное приведение типа. AS>- Оставить один общий тип для всех хэндлов. При этом "лишние" приведения типа не требуются, но теоретически может возникнуть неоднозначность.
AS>Разработчики из МС выбрали второй путь.
Они выбрали оба пути. По крайней мере ранние SDK имели вариант компиляции, при котором все эти HWND, HFILE... превращались в разные объекты (фактически примерно так:
typedef struct { что-то; } FAR *HFILE;
) и передача одного в другой без конверсии вызывала ошибку компиляции. Возможно, это сейчас уже отменили — не смотрел.
AS>>Разработчики из МС выбрали второй путь.
N>Они выбрали оба пути. По крайней мере ранние SDK имели вариант компиляции, при котором все эти HWND, HFILE... превращались в разные объекты (фактически примерно так:
typedef struct { что-то; } FAR *HFILE;
) и передача одного в другой без конверсии вызывала ошибку компиляции. Возможно, это сейчас уже отменили — не смотрел.
Есть, точно есть. В VC 2005 по умолчанию это именно так.
Здравствуйте, netch80, Вы писали:
N>Они выбрали оба пути. По крайней мере ранние SDK имели вариант компиляции, при котором все эти HWND, HFILE... превращались в разные объекты (фактически примерно так:
typedef struct { что-то; } FAR *HFILE;
) и передача одного в другой без конверсии вызывала ошибку компиляции. Возможно, это сейчас уже отменили — не смотрел.
Это не совсем так. В SDK есть макрос STRICT, который превращает некоторые хэндлы в типизированные объекты. Вот фрагмент из winnt.h:
С помощью DECLARE_HANDLE определяются такие хэндлы как HWND, HDC, HPEN/HBRUSH/HFONT и т. д. Поскольку без макроса STRICT практически никто не работает (визард вставляет его в проект по умолчанию), эти объекты приводить друг к другу неявно не получится.
Но для объектов ядра DECLARE_HANDLE не используется. Они всегда именно HANDLE, никаких HPROCESS/HTHREAD/HCONSOLE на уровне SDK не существует. Именно об этом говорил Odi$$ey.
--
Я думал, ты огромный страшный Бажище,
А ты недоучка, крохотный Бажик...
Здравствуйте, Sinclair, Вы писали:
S>А написать file->pos тебе поможет среда с автодополнением, и компилятор ничего плохого не скажет.
Ну, если мы будем оценивать "ООП это или нет" по подобным критериям, то... на этом мысль останавливается.
S>Ребята, может хватит детский сад разводить?
Именно к этому я и призываю.
S>Вам что, в школе не преподавали структурное программирование? Или вы его узнать не можете, даже посмотрев на него вплотную?
Просто термин "ООП" стал каким-то жупелом, страшилкой для детей. А на самом деле, король-то голый. Нет ни малейшей принциальной разницы между read(file...) и file.read(...). И разговоры про ОО API не имеют смысла.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
McSeem2 wrote: > Просто термин "ООП" стал каким-то жупелом, страшилкой для детей. А на > самом деле, король-то голый. Нет ни малейшей принциальной разницы между > read(file...) и file.read(...). И разговоры про ОО API не имеют смысла.
Бывают и не OO-API Вспомни тот же OpenGL.
Здравствуйте, Cyberax, Вы писали:
C>Бывают и не OO-API Вспомни тот же OpenGL.
Ну, если уж ёрничать, то OpenGL — это тоже ОО API. Просто там один-единственный stateful объект (паттерн "singleton"), а параметр "this" — неявный (в виде глобальных состояний), но незримо присутствующий и подразумеваемый. В конечном итоге, сущность определяется не API, а протоколом видео-железки. А железяка является принципиально stateful и она одна. С этой точки зрения, D3D ничуть не более объектно-ориентирован, чем OpenGL. Какие бы ОО-навороты ни прикручивались к этой железяке, по сути API останется той же strtok, то есть, stateful singleton.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
McSeem2 wrote: > C>Бывают и не OO-API Вспомни тот же OpenGL. > Ну, если уж ёрничать, то OpenGL — это тоже ОО API. Просто там > один-единственный stateful объект (паттерн "singleton")
Контекстов, кстати, там может быть несколько — их можно переключать.
Кроме того, у каждого потока может быть свой контекст.
> а параметр > "this" — неявный (в виде глобальных состояний), но незримо > присутствующий и подразумеваемый.
Там, кстати, еще и типы объектов можно менять — 1d-текстуру "легким
движением руки" превратить в 2d-текстуру, например.
> В конечном итоге, сущность > определяется не API, а протоколом видео-железки. А железяка является > принципиально stateful и она одна. С этой точки зрения, D3D ничуть не > более объектно-ориентирован, чем OpenGL. Какие бы ОО-навороты ни > прикручивались к этой железяке, по сути API останется той же strtok, то > есть, stateful singleton.
Ну... Те же текстуры и сетки, при желании, можно полноценными объектами
представлять (даже на уровне железа).
Здравствуйте, konsoletyper, Вы писали:
K>Приведу пример с теми же матрицами. Если матрицу сделать объектом, то матрица должна быть изменяемой. Т.е. должны быть такие сообщения, которые изменяют отдельные компоненты. При этом разумно к объекту "матрица" прикрутить события. Иначе, если мы присвоим матрицу 4-го порядка чему-нибудь вроде RenderingDevice, а потом станем изменять её компоненты, то это никак не затронет картинку, воспроизводимую RenderingDevice. Кроме того, уже не будет объекта IdentityMatrix типа Matrix, поскольку его можно будет изменить и это будет уже не IdentityMatrix. Вместо этого нужно будет иметь singletone-объект IdentityMatrixMaker, который будет посылать данной матрице такую серию сообщению, которая сделает её единичной.
Ну дак от этого она не перестанет быть объектом... ГЫ
Здравствуйте, FDSC, Вы писали:
FDS>Ну дак от этого она не перестанет быть объектом... ГЫ
ИМХО, речь идёт о программировании на уровне литералов. 1, 2, 7, 42 — это литералы, то есть "конструкторы" для типа int специального, перечислительного, вида. Идея в том, чтобы это расширить; скажем, {1, 5, 7, 42} — такой же перечислительный конструктор для массива из 4 элементов. Это не объекты, поскольку их идентити определяется не их местоположением в памяти (которое нас и не интересует), а их декларированной внутренней структурой. Точно также как 1 всегда тождественно равна 1, независимо ни от чего, {1, 5, 7, 42} всегда тождественно равен {1, 5, 7, 42} и ничему другому.
Здравствуйте, McSeem2, Вы писали:
S>>Вам что, в школе не преподавали структурное программирование? Или вы его узнать не можете, даже посмотрев на него вплотную?
MS>Просто термин "ООП" стал каким-то жупелом, страшилкой для детей. А на самом деле, король-то голый. Нет ни малейшей принциальной разницы между read(file...) и file.read(...).
Есть. read(file) неполиморфмен. file.read() мы можем переопределить в производном классе. Вызывающий код останется тем же.
Я уж не говорю про инварианты, RAII и гарантии безопасности исключений.
MS> И разговоры про ОО API не имеют смысла.
-1.
Это совершенно разные стили. В ОО API мы как правило можем воспользоваться полиморфизмом и отнаследововашись от стандартных объектов модифицировать их поведение где надо.
Андрей Хропов wrote: > Есть. read(file) неполиморфмен. file.read() мы можем переопределить в > производном классе. Вызывающий код останется тем же.
Ну так создай свое устройство — и работай с ним через read(file).
Просто file полиморфен на уровне ОС, а не на уровне приложения.
> Я уж не говорю про инварианты, RAII и гарантии безопасности исключений.
Все есть. Open/create — конструтор, close — деструктор.
Здравствуйте, konsoletyper, Вы писали:
S>>С точки зрения теории кристалла это совершенно ненужная, а иногда и вредная оптимизация. K>А это что такое? http://www.rusf.ru/vk/recen/1998/wt-t-03.htm
S>>Смешиваешь две несвязанные вещи. Создание новых матриц — это аналог "виртуальной" памяти. Т.е. потребителю всё равно кажется, что матрицы были там всегда.
K>Это я не смешиваю две вещи, а просто говорю об одном из способов эмулировать нужную сущность.
Смешиваешь. Переопределение Equals и способ конструирования объектов никак не связаны. Точнее, так: перегрузка Equals нужна только в тех случаях, если среда позволяет создать более одного эквивалентного объекта.
K>Правильно, можно сам язык и рантайм (если таковой имеется) основать на нескольких простейшимх вещах. Но это никак не должно мешать нам о некоторых вещах думать немного-по другому.
Как раз наоборот. То, что в некоторых рантаймах для value-типов сделана отдельная поддержка, не должно мешать нам думать об этих вещах по-другому. Иначе всю жизнь будешь думать, что int — это int, а никак не object.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Так в чем же принципиальные отличия ФП от ИП?
Здравствуйте, Odi$$ey, Вы писали:
OE>BOOL SetConsoleCursorPosition( OE> HANDLE hConsoleOutput, OE> COORD dwCursorPosition OE>);
OE>BOOL WriteFile( OE> HANDLE hFile, OE> LPCVOID lpBuffer, OE> DWORD nNumberOfBytesToWrite, OE> LPDWORD lpNumberOfBytesWritten, OE> LPOVERLAPPED lpOverlapped OE>);
OE>таки "Никакого такого соответствия между handle и функциями их принимающими в winapi не наблюдается"
В никсах, кстати, объект "файл" может быть чем угодно — файлом на диске, сети, устройством, пайпом, сокетом т.п. — используются одни и те же функции read/write. Такое же подобие есть и в винде: посмотрите, какие объекты может создавать CreateFile, а лучше, какие может закрывать CloseHandle. Что это значит? Что HANDLE — некий базовый объект, у которого есть некий базовый интерфейс (CreateFile/CloseHandle) и унаследованные объекты (File, Directory, Driver, Console), у которых может быть расширенный интерфейс (WriteConsole, DeviceIoControl).
Другое дело, что типизации почти нет, т.к. в си всё typedef — просто синонимы, поэтому HWND можно привести к HANDLE, но и это попытались обойти через DECLARE_HANDLE. А ведь на самом деле HANDLE — тот же неявный указатель на объект.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Gaperton, Вы писали: G>>Если структура FILE стандартизована, и одинакова во всех реализациях — тогда она прозрачна. А если нет — то нет. И неважно, можно к ней добраться, или нельзя. Также как и недокументированные функции API — ты можешь их использовать, но этого делать нельзя — они не являются частью стандартизованного public интерфейса, и могут в следующей версии вообще уйти. И не важно, пусть даже эта недокументированная функция сейчас присутствует во всех реализациях. S>Недокументированность функций имеет слабое отношение к теме вопроса. Речь о том, что handle — это не указатель на структуру, а некоторый селектор в неизвестно куда. И работать с ним можно исключительно путем вызова функций, пусть даже и недокументированных.
Самое прямое отношение. Если у тебя file->pos (наличие поля pos в структуре FILE, и вообще — что это структура) не закреплено стандартом, то так писать нельзя, независимо от того, дает тебе тулза комплит или нет.
G>>Я к приватным данным твоего класса тоже пролезу без проблем, кстати, если захочу. #define private public, #include "you_private_class" — и вперед. Вывод? Да С++ говно язык, не ООП ни разу, никакой инкапсуляции не обеспечивает . Как я могу думать об инкапсуляции, если они, privat-ы, у меня как на ладони? S>Ну, по крайней мере, ты сделаешь это осознанно. А написать file->pos тебе поможет среда с автодополнением, и компилятор ничего плохого не скажет.
S>Ребята, может хватит детский сад разводить? Вам что, в школе не преподавали структурное программирование? Или вы его узнать не можете, даже посмотрев на него вплотную?
Преподавали. Я тебе и пытался реультат того преподавания донести. Если эта стандарт на АПИ определяет, что FILE — это структура, и состав ее полей, то тогда я соглашусь с тобой — это структурное программирование. Если же ты оперируешь хэндлами — то извини. Это ООП — интерфейс у тебя абстрактный.
Кстати, в WinAPI дофига структур описано в документации. И при этом, случаются и абстрактные интерфейсы.
G>Преподавали. Я тебе и пытался реультат того преподавания донести. Если эта стандарт на АПИ определяет, что FILE — это структура, и состав ее полей,
Стандарт определяет, что FILE — это структура. Обрати внимание, что везде используется FILE*. То, что ее состав полей нестандартизован — это попытка исправить допущенную ошибку. G> то тогда я соглашусь с тобой — это структурное программирование. Если же ты оперируешь хэндлами — то извини. Это ООП — интерфейс у тебя абстрактный.
G>Кстати, в WinAPI дофига структур описано в документации. И при этом, случаются и абстрактные интерфейсы.
Это ничему не противоречит. Ну вот например CreateFontIndirect использует документированную структуру LogFONT для создания HFONT.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
А изменения instruction pointer (после любой команды) — континуации?
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, VladD2, Вы писали:
VD>Кстати, когда проектировали NT (потомки которой сейчас и назваются Виндовс), то на полном серьезе рассматривали решение использовать С++ для написания этой ОС. Но отвергли это решение такак (гы-гы) в те времена считалось, что С++ создает неприемлемо большой оверхэд.
Именно. А при выборе между поддерживающим переменое число аргументов __cdecl-соглашении о вызове функций и более быстрым благодаря отсутствию накладных расходов на генерацию кода очистки стека __stdcall- соглашением, Microsoft предпочел последний.
Это я к тому, что при проектировании WinAPI, MS$ прежде всего ориентировался на производительность. А уж рассмотреть ООП в получившимся чисто-процедурном API при желании можно. А при большом желании, ООП можно найти и в ассемблере здесь
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Это я к тому, что при проектировании WinAPI, MS$ прежде всего ориентировался на производительность. А уж рассмотреть ООП в получившимся чисто-процедурном API при желании можно. А при большом желании, ООП можно найти и в ассемблере здесь
Ага предпочли. Жаль, что их выобр оказалвся на 99% фобиями и глупостью. С++ за время разработки NT вдруг стал генерировать код не хуже С-шного, а stdcall (или если быть более точным паскалевское соглашение) оказалось не таким быстрым как тот же fastcall используемый сегодноя в дотнете.
Это замечательная иллюстрация того как неверные предположения и зилишняя перестраховка может изуродовать дизайн огромной системы.
В прочем, это уже освсем дургая тема...
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Это замечательная иллюстрация того как неверные предположения и зилишняя перестраховка может изуродовать дизайн огромной системы.
Фигня Эт ты симбиана не видел Там боязнь С++-исключений у системных архитекторов привела к ТААААКОЙ кривизне дизайна всей системы — обнять и плакать...