Re[8]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Дарней Россия  
Дата: 21.10.04 04:25
Оценка: +2
Здравствуйте, LaptevVV, Вы писали:

LVV>Ага! Значит роль Вирта — тож ноль! Он же ничего не создал толкового! Но уже один только факт, что мы спорим о нем — говорит о противоположном!

LVV>И Дейкстра тож нифига, кроме семафоров не оставил. А уж о грисе вообще можно не говорить, так же как о Хоаре. Или о Шелле — подуманешь, сортировку придумал, блин! Да фигня полная!
LVV>Так что ли?

Нет, не так. Роль Вирта вполне заслуживает уважения, по крайней мере — когда он начинал. Вызывают недоумение его дальнейшие метания в непонятных направлениях, и в особенности — та статья, с обсуждения которой началась эта тема. Потому что отдельные элементы в ней выглядят достойно только для темы в holy wars, например — "почему я ненавижу С++", а не для великого ученого.

LVV>Вот и подумайте. О себе, в первую очередь, а не о Вирте.


Как сказал Марк Твен (если не ошибаюсь) — даже если я не снес за свою жизнь ни одного яйца, это не отнимает у меня право оценивать качество омлета.
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[21]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.04 05:57
Оценка: +1
Здравствуйте, Kh_Oleg, Вы писали:

K_O>То есть, если часть группы использует другой компилятор, то ей все равно придется все перекомпилять? Да я все равно сомневаюсь, что такой эскпорт работает без глюков и side-эффектов.

Если часть группы использует другой компилятор, то ей придется разрабатывать другой продукт. Несовместимость компиляторов — один из основных факторов, подтачивающих будущее программирования на плюсах.
Если при этом компилятор еще и плохо поддерживает стандарт даже "внутри себя", то его наверное стоит заменить каким-нибудь другим.

С точки зрения теории кристалла, нет никаких ограничений на динамическое связывание классов/объектов. Точно так же, как введение ООП в плюсы не потребовало никаких изменений в линкере, никаких изменений не потребуется и от модели DLL или что там вместо них в унихах. Банально потому, что функции отложенной линковки сводятся к поиску адреса по имени. Точка. А что это за адрес — процедура, метод, VMT, или объект — рантайму по барабану.
Так что твои заявления об ограничениях DLL — не более чем проявление некомпетентности.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[22]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.10.04 06:48
Оценка:
Здравствуйте, FR, Вы писали:

K_O>>Ну так как насчет простенького примера экспорта собственного класса? Мне просто любопытно на это взглянуть...


FR>Я же тебе привел уже пример STLPort, глюков не наблюдал.


FR>Простеший пример:


FR>
FR>#ifndef _DLL_H_
FR>#define _DLL_H_

FR>#if BUILDING_DLL
FR># define DLLIMPORT __attribute__((dllexport))
FR>#else /* Not BUILDING_DLL */
FR># define DLLIMPORT __attribute__((dllimport))
FR>#endif /* Not BUILDING_DLL */


FR>class DLLIMPORT DllClass
FR>{
FR>  public:
FR>    DllClass();
FR>    virtual ~DllClass(void);

FR>    int Method();
FR>    virtual int VirtualMethod();

FR>  private:

FR>};


FR>#endif /* _DLL_H_ */
FR>


Если я не ошибаюсь, выделенные места являются compiler-specific. MSVC++ 7.1 здесь поперхнулся.

FR>def файл:


FR>
FR>LIBRARY     LIB.DLL

FR>EXPORTS
FR>    _ZN8DllClass13VirtualMethodEv  @8   
FR>    _ZN8DllClass6MethodEv          @1   
FR>    _ZN8DllClassC1Ev               @2   
FR>    _ZN8DllClassC2Ev               @3   
FR>    _ZN8DllClassD0Ev               @4   
FR>    _ZN8DllClassD1Ev               @5   
FR>    _ZN8DllClassD2Ev               @6   
FR>    _ZTV8DllClass                  @7   
FR>


Хм.... Эту абракадабру я сам должен писать?

Ну и наконец, как в другом экзешнике заиспользовать этот класс? Смогу ли я, просто подключив dll.h у себя написать:
DllClass* pClass = new DllClass();

class MyDllClass : public DllClass
{
  ...
};


И все нормально скомпиляется (в этом я не сомневаюсь), слинкуется и запустится?
Re[22]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.10.04 07:10
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>С точки зрения теории кристалла, нет никаких ограничений на динамическое связывание классов/объектов. Точно так же, как введение ООП в плюсы не потребовало никаких изменений в линкере, никаких изменений не потребуется и от модели DLL или что там вместо них в унихах. Банально потому, что функции отложенной линковки сводятся к поиску адреса по имени. Точка. А что это за адрес — процедура, метод, VMT, или объект — рантайму по барабану.


При условии, что в Dll присутствуют имена и адреса методов и VMT. Платформно-переносимыми и не зависящими от компилятора являются только адреса и имена обычных С-шных функций.

S>Так что твои заявления об ограничениях DLL — не более чем проявление некомпетентности.


Уважаемые, мне не нужны ваши теоретические измышления. Есть проблема — разделить программу на С++ на Dll'ки. Причем, сделать это так, чтобы компилировалось и работало на одних и тех же исходниках и по крайней мере на тех четырех компиляторах, о которых я сказал. Если кто-нибудь сталкивался с подобным — расскажите, как это можно сделать, если подобного опыта нет — нечего сотрясать воздух.

Два решения я уже озвучил — С-подобные функции-врапперы и создание собственного COM'а. Ни то, ни другое не подходит ввиду огромного объема работы, которую придется проделать.
Re[23]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kluev  
Дата: 21.10.04 07:24
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:

K_O>Уважаемые, мне не нужны ваши теоретические измышления. Есть проблема — разделить программу на С++ на Dll'ки. Причем, сделать это так, чтобы компилировалось и работало на одних и тех же исходниках и по крайней мере на тех четырех компиляторах, о которых я сказал. Если кто-нибудь сталкивался с подобным — расскажите, как это можно сделать, если подобного опыта нет — нечего сотрясать воздух.


Как правило делают конфиг-h файл куда выносят все компилер-специфик вещи
типа __declspec(dllexport) или __attribute__(dllexport) и т.п. Это можно сделать т.к. живет же QT под линуксом и под виндой в dll-ях.
Более того я бы позаботился о обратной двоичной совместимости, т.е. для классов хорошо бы заюзать расширенный паттерн p-impl с поддержкой наследования.

class MyClass {
   void   *pImpl_; // указатель на структуру данных этого класса
public:
   void foo();
   void zoo();
   void bar();
};


тогда можно будет править реализацию не ломая интерфейс и не перекомпилируя клиента этой DLL
Re[23]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: FR  
Дата: 21.10.04 07:25
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:


K_O>Если я не ошибаюсь, выделенные места являются compiler-specific. MSVC++ 7.1 здесь поперхнулся.


Ну я уже не знаю чего ты хочешь, ты же пример для gcc просил вроде.
Если gcc >= 3.0 (или 2.9 не помню уже) то он понимает и ms вариант того же объявления, то есть:

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */


этот вариант нормально работает и на bcc, то есть на всех распрастранненых в windows компиляторах.

K_O>Хм.... Эту абракадабру я сам должен писать?


нет это само генерируется, я привел как пример, что получается на выходе, вот более
подробный листинг:

EXPORTS
    _ZN8DllClass6MethodEv @ 1 ; DllClass::Method()
    _ZN8DllClassC1Ev @ 2 ; DllClass::DllClass()
    _ZN8DllClassC2Ev @ 3 ; DllClass::DllClass()
    _ZN8DllClassD0Ev @ 4 ; DllClass::~DllClass()
    _ZN8DllClassD1Ev @ 5 ; DllClass::~DllClass()
    _ZN8DllClassD2Ev @ 6 ; DllClass::~DllClass()
    _ZTV8DllClass @ 7 DATA ; vtable for DllClass
    _ZN8DllClass13VirtualMethodEv @ 8 ; DllClass::VirtualMethod()


K_O>Ну и наконец, как в другом экзешнике заиспользовать этот класс? Смогу ли я, просто подключив dll.h у себя написать:

K_O>
K_O>DllClass* pClass = new DllClass();

K_O>class MyDllClass : public DllClass
K_O>{
K_O>  ...
K_O>};
K_O>


K_O>И все нормально скомпиляется (в этом я не сомневаюсь), слинкуется и запустится?


Нормально все работает, на этом уже кучи программ и библиотек построены. Главное не забыть компилировать и dll и exe с одной и той же динамичесой версией RTL.
Вообще посмотри плюсовые RTL dll от ms или борланд, экспортируются кучи классов типа std::fstream, std::string и т. п.
... << RSDN@Home 1.1.3 stable >>
Re[9]: А Вы хоть знаете что такое WITH?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.10.04 08:07
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>Ни что не мешает делать аналогичную оптимизацию для WITH по сравнению с цепочкой dynamic_cast-ов.

WH>Уф... Ты мне объясни на кой черт нужна эта цепочка if'ов вобще? Не надо мне объяснять как это работает. Поверь мне я это не хуже тебя знаю. Ты мне скажи зачем в язык введена конструкция которая не нужна.

Вы в курсе, что изначально ООП основывается вовсе не на трех китах 1) наследование, 2) полиморфизм, 3) инкапсуляция; а всего на одной простой идее: все есть объекты и объекты обмениваются друг с другом сообщениями? Вот пришло к объекту сообщение закодированное в виде числа, как объекту догадаться что это за сообщение? Ему надо либо цепочкой if-else проверить это число с теми числами сообщений которые он понимает, либо сделать это с помощью CASE.


Вариант 1:
IF msg_code = 6 THEN 
  сделать_одно_действие
ELSIF msg_code = 234 THEN 
  сделать_другое_действие
ELSIF msg_code = 902 THEN 
  сделать_третье_действие
END;


Вариант 2:
CASE msg_code OF
  6  : сделать_одно_действие   |
  234: сделать_другое_действие |
  902: сделать_третье_действие
ELSE
  (* данная сообщение не опознано *)
END;


Допустим, есть N-вариантов. Тогда цепочка IF-ELSE будет в худшем случае делать O(N) проверок, в то время как CASE будет выполнять не более O(Log(N)) проверок.

Например, вполне реальное число N = 20, Log(20) = 4.3, т.е. разница что-то около 5 раз, нужна такая конструкция в языке или нет?

А WITH — это тот же CASE, но только по типам с учетом иерархии наследования.
TYPE
  Message = EXTENSIBLE RECORD 
    (* ... *)
  END;

  SomeMsg = RECORD (Message)
    (* ... *)
  END;

  AnotherMsg = RECORD (Message)
    (* ... *)
  END;

  ThirdMsg = RECORD (Message)
    (* ... *)
  END;

PROCEDURE (v: View) HandleMsg (VAR msg: Message);
BEGIN
  WITH 
    msg: SomeMsg    DO сделать_одно_действие   |
    msg: AnotherMsg DO сделать_другое_действие |
    msg: ThirdMsg   DO сделать_третье_действие
  ELSE 
    (* данная сообщение не опознано *)
  END;
END HandleMsg;

Причем внутри блока кода "сделать_XXX_действие" переменная msg трактуется так как буд-то ее статический тип есть тот тип который и был опознан. Например, внутри блока кода "сделать_одно_действие" статический тип переменной msg есть тип "SomeMsg", а вовсе не просто "Message".
Re: Вы чего!!!
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.10.04 08:12
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Перестаньте позорить чистое имя Вирта наглым пренебрежением к LSP!!! За подобные последовательности в нормальном промышленном коде нужно обрывать руки и предавать анафеме до конца семестра.


Простите, Вы с чем-то не согласны?
Re[14]: *
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.10.04 08:17
Оценка: :)))
Здравствуйте, Геннадий Васильев, Вы писали:

СГ>>Шаблоны позволяют меньше ручками по клавиатуре долбить.


ГВ>2. Процедуры, функции, и прочее подобное предназначены для того же. И что из этого следует?


Процедуры и функции во время исполнения программы таки есть (помните такую команду call)? А вот шаблонов нет, то есть шаблоны не увеличивают возможностей программы.
Re[24]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.10.04 08:17
Оценка:
Здравствуйте, Kluev, Вы писали:

K>Это можно сделать т.к. живет же QT под линуксом и под виндой в dll-ях.


А ведь и в самом деле... Надо будет посмотреть, что там да как.
Re[10]: А Вы хоть знаете что такое WITH?
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.04 08:37
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Например, вполне реальное число N = 20, Log(20) = 4.3, т.е. разница что-то около 5 раз, нужна такая конструкция в языке или нет?

А почему бы компилятору не привести в обоих случаях код к одинаковому виду? Ты почему-то начинаешь делать какие-то предположения о исполнении программы на ЯВУ. В общем случае говорить об оптимальности какой-либо конструкции такого языка — вообще бред. Особенно сравнивая две семантически эквивалентных конструкции.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: *
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.04 08:37
Оценка: 14 (3) +2
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Процедуры и функции во время исполнения программы таки есть (помните такую команду call)?

Ну при чем здесь сall? Уберите call — будут делать push/jump. Кстати, техника с джампами применяется в компилерах направо и налево. А инлайнинг? Вообще состояние физической машины во время исполнения весьма косвенным образом связано с текстом исходной программы.
СГ>А вот шаблонов нет, то есть шаблоны не увеличивают возможностей программы.
Вот это вообще бред. Все возможности программы были внятно описаны еще до второй мировой войны. Ты с тезисом Черча знаком? Так вот никакие техники программирования, известные на данный момент, ничего не добавляют к понятию вычислимости, введенному сто лет назад.

Тем не менее, программирование на месте не стоит. Потому, что нас интересует увеличение возможностей программиста, а не программы. И вот шаблоны эти возможности как раз увеличивают. Равно как и процедуры, функции, объекты, классы, делегаты, функторы и прочие абстракции.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: *
От: Alex Reyst Россия  
Дата: 21.10.04 08:42
Оценка: 7 (1) +1
Здравствуйте, WolfHound, Вы писали:

WH>А что он сделал? Несколько ни кому не нужных языков которые по сути не далеко ушли от ассемблера? Развел кучу тупых наездов на С/С++ из серии := vs = ? Создал культ поклонения Оберону? Ты посмотри на Губанова... он же просто фанатеет от оберонов.


Он впервые попытался — и преуспел в своей попытке — соединить практику программирования, математические основы программирования, методику преподавания программирования — "в одном флаконе".

И то, что сейчас его действительно "зашкаливает", — это отнюдь не повод относиться неуважительно к человеку, прервавшего в свое время весьма порочную ассоциацию "программирование = Фортран".
Все, что здесь сказано, может и будет использоваться против меня...
Re[15]: *
От: prVovik Россия  
Дата: 21.10.04 08:46
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Процедуры и функции во время исполнения программы таки есть (помните такую команду call)? А вот шаблонов нет, то есть шаблоны не увеличивают возможностей программы.


Ну а какие дополнительные возможности предоставляет команда call? Что мешает руками запихать адрес возврата в стек и сделать jmp? То есть нет никаких дополнительных возможностей.
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re[10]: А Вы хоть знаете что такое WITH?
От: Дарней Россия  
Дата: 21.10.04 08:48
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Вы в курсе, что изначально ООП основывается вовсе не на трех китах 1) наследование, 2) полиморфизм, 3) инкапсуляция; а всего на одной простой идее: все есть объекты и объекты обмениваются друг с другом сообщениями? Вот пришло к объекту сообщение закодированное в виде числа, как объекту догадаться что это за сообщение? Ему надо либо цепочкой if-else проверить это число с теми числами сообщений которые он понимает, либо сделать это с помощью CASE.


Когда нужно делать такое большое количество проверок, цепочку из if-else пишут только самые начинающие. Если у человека есть хоть какой-то опыт, то он будет использовать дерево поиска или хэш-таблицу, и получит то же самое быстродействие. Рекомендую ознакомиться с реализацией оконных функций в MFC — там именно так и сделано.
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[11]: А Вы хоть знаете что такое WITH?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.10.04 09:30
Оценка:
Здравствуйте, Дарней, Вы писали:


Д>Когда нужно делать такое большое количество проверок, цепочку из if-else пишут только самые начинающие. Если у человека есть хоть какой-то опыт, то он будет использовать дерево поиска или хэш-таблицу, и получит то же самое быстродействие. Рекомендую ознакомиться с реализацией оконных функций в MFC — там именно так и сделано.


Для пользовательских типов да, так и надо сделать, но для перечислимых типов компилятор сам превратит CASE/switch в хэш таблицу или в дерево поиска! Так как перечислимые типы используются очень часто, то и была придумана структурирующая конструкция CASE/swicth.

Вот и получаем, что раз нет разницы, то зачем платить больше...
Re[11]: А Вы хоть знаете что такое WITH?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.10.04 09:41
Оценка: -2
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Сергей Губанов, Вы писали:


S>А почему бы компилятору не привести в обоих случаях код к одинаковому виду?


А потому что язык императивный. Когда программист пишет цепочку ELSIF то он именно требует от компьютера того чтобы сначала было проверено первое условие, если оно ложно, то после него надо проверить именно второе условие и т.д. ПОСЛЕДОВАТЕЛЬНО по цепочке.
IF b1 THEN s1 ELSIF b2 THEN s2 ELSIF b3 THEN s3 ELSE sDefault END

Проверка условия b1, теоретически, может изменять состояние системы, что в свою очередь, может влиять на результаты выполнения условий b2 и b3. Поэтому, если в программе указана именно такая цепочка, то компьютер и должен проверять условия именно так как указано. Если программисту все равно в каком порядке проверять условия, то он должен использовать операцию множественного выбора условия, т.е. CASE/switch. Это же азбука, основа построения алгоритмов, а Вы по ней вопросы задаете. И как после этого не согласиться с утверждением, что большинство программистов малограмотны...
Re[12]: А Вы хоть знаете что такое WITH?
От: Kluev  
Дата: 21.10.04 09:42
Оценка:
СГ>Здравствуйте, Дарней, Вы писали:

Д>>Когда нужно делать такое большое количество проверок, цепочку из if-else пишут только самые начинающие. Если у человека есть хоть какой-то опыт, то он будет использовать дерево поиска или хэш-таблицу, и получит то же самое быстродействие. Рекомендую ознакомиться с реализацией оконных функций в MFC — там именно так и сделано.


switch-case по типам весьма полезная штука. Т.к. if + dynamic_cast компилер не прооптимизирует.
Re[12]: А Вы хоть знаете что такое WITH?
От: WolfHound  
Дата: 21.10.04 10:16
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>А потому что язык императивный.

И что с того?
СГ>Когда программист пишет цепочку ELSIF то он именно требует от компьютера того чтобы сначала было проверено первое условие, если оно ложно, то после него надо проверить именно второе условие и т.д. ПОСЛЕДОВАТЕЛЬНО по цепочке.
Ну если расматривать сферического коня в вакууме то да.
А если функцию вида
int foo(int i)
{
    if(i == 1)    return 2;
    if(i == 2)    return 5;
    if(i == 3)    return 3;
    if(i == 4)    return 38;
    if(i == 5)    return 20;
    if(i == 6)    return 50;
    if(i == 7)    return 30;
    if(i == 8)    return 380;
    return 255;
}

то здесь явно видно что интересующая нас часть машины не изменится и ни что не мешает компилятору этим воспользоваться. Болие того в данном случае не сложно определить что это чистая функция со всеми вытекающими.

СГ>И как после этого не согласиться с утверждением, что большинство программистов малограмотны...

Во-во... учите матчасть... А также пятый пункт обязательных правил RSDN.
... << RSDN@Home 1.1.4 rev. 185 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: А Вы хоть знаете что такое WITH?
От: Kluev  
Дата: 21.10.04 10:28
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>А потому что язык императивный.

WH>И что с того?
СГ>>Когда программист пишет цепочку ELSIF то он именно требует от компьютера того чтобы сначала было проверено первое условие, если оно ложно, то после него надо проверить именно второе условие и т.д. ПОСЛЕДОВАТЕЛЬНО по цепочке.
WH>Ну если расматривать сферического коня в вакууме то да.
WH>А если функцию вида
WH>
WH>int foo(int i)
WH>{
WH>    if(i == 1)    return 2;
WH>    if(i == 2)    return 5;
WH>    if(i == 3)    return 3;
WH>    if(i == 4)    return 38;
WH>    if(i == 5)    return 20;
WH>    if(i == 6)    return 50;
WH>    if(i == 7)    return 30;
WH>    if(i == 8)    return 380;
WH>    return 255;
WH>}
WH>

WH>то здесь явно видно что интересующая нас часть машины не изменится и ни что не мешает компилятору этим воспользоваться. Болие того в данном случае не сложно определить что это чистая функция со всеми вытекающими.

Когда у нас кодец вида:
if ( A *a = dynamic_cast<A*>(p)) return ...;
if ( B *b = dynamic_cast<B*>(p)) return ...;

То компилер это не прооптимизирует. А встроенный свитч по типам наверное бы смог. Так что это фича весьма полезная в некоторых случаях. Например какойнить протокол обмена из 5х-10и сообщений. Когда делать хеш будет в лом. if — будет криво, а встроенный свитч по типам весьма бы подошел.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.