2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 
Сообщение12.01.2006, 13:33 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Еще такой вопрос к тем, кто пишет на С++ "часто и по-многу" :) . Как вы оцениваете качество кода? По каким критериям определяете - хорош код или плох?

Да, и вот еще какая штука... Наверно, каждый, кто пытался писать свою библиотеку классов для Windows на C++ сталкивался с таким неприятным фактом, как невозможность взятия адреса функции-члена класса. Т.е. вот так просто взять и назначить какую-то функцию-член класса оконной функцией не выходит никак, хоть тресни! Приходится идти всякими достаточно кривыми путями... Один из самых приличных (что мне известны) описан в книжке "Программирование графики для Windows" (автора счас не помню).
Вопрос:
- с чем связано такое ограничение в C++? С принципиальной сложностью в создании такого компилятора, который бы все это обеспечивал? Или еще с чем-то?
- Если кто-то сталкивался с подобным ограничением, как Вы его обходили?

 Профиль  
                  
 
 
Сообщение12.01.2006, 19:08 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Sanyok писал(а):
Еще такой вопрос к тем, кто пишет на С++ "часто и по-многу" :) . Как вы оцениваете качество кода? По каким критериям определяете - хорош код или плох?

Искони критерий один - коэффициент расширения. По времени, по памяти (программы, данных). Определяется как во сколько раз программа больше, чем написанная "вручную" грамотным программистом. Разумеется, он не меньше единицы, так как грамотный программист начинает с порожденного компилятором кода, и не связан ограничениями компилятора / языка.

Когда С++ появился, компиляторы С были прилично "вылизаны", что и создало С++ репутацию громоздкости, тяжеловесности. Не то сейчас. Кроме того, с годами процессоры становятся круче, и кого волнуют эти 5-10-20%. А вот когда волнуют -- переписывают небольшой кусок на ассемблере так, что выигрыш 50+%. Доходила до меня сплетня, что smooth scroll loop в MS Word был так переписаан. Но и трудозатраты при этом велики.


Sanyok писал(а):
Наверно, каждый, кто пытался писать свою библиотеку классов для Windows на C++ сталкивался с таким неприятным фактом, как невозможность взятия адреса функции-члена класса. Т.е. вот так просто взять и назначить какую-то функцию-член класса оконной функцией не выходит никак, хоть тресни! ... Вопрос:
- с чем связано такое ограничение в C++? С принципиальной сложностью в создании такого компилятора, который бы все это обеспечивал? Или еще с чем-то?
- Если кто-то сталкивался с подобным ограничением, как Вы его обходили?

Ограничение связано с неявной передачей параметра -- ссылки на экземпляр -- в метод. Поскольку Виндузе никак не может узнать ссылку на экземпляр, то вызвать корректно метод - никакими силами.

Все это, естественно, относится к нестатическим методам. Статические методы передавай - сколько влезет. Только вот они доступа к экземпляру не имеют.

Поэтому, если я помню правильно, обычно делается статическая функция в классе, а ссылка на экземпляр сохраняется как пользовательский параметр dwRefData. Все, что делает статическая функция - typecast(dwRefData)->rightmethod(...).

Задача сия решена в некоторых языках -- введена частичная параметризация. Можно написать foo = bar(a, b, *, *) или f = obj->g, после чего foo(p, q) и f(x) эквивалентны bar(a, b, p, q) и obj->g(x), соответственно. В С++ этого нет, механизм вообще более характерен для динамических языков. У частичной параметризации много аргументов за -- поддержка парадигмы функционального программирования, однократное вычисление параметров, ...

Добавлю, что это отнюдь не единственный случай. Для меня более частым примером является создание процесса - нужно передать функцию, а у меня процесс намертво связан с объектом. Хорошо хоть, большинство OS позволяет передать в новый процесс указатель параметром. И все равно коряво до безобразия...

 Профиль  
                  
 
 
Сообщение12.01.2006, 19:18 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Млин, насчет качества кода неверно задал вопрос...
Я имел в виду качество исходного текста... Я текст кодом обозвал... :oops: Насчет второго вопроса - я Ваши объяснения не совсем понял.. :oops: Вы не могли бы статейку посоветовать где это расписано, или хотя бы по каким ключевым словам искать?

 Профиль  
                  
 
 
Сообщение12.01.2006, 19:24 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Sanyok писал(а):
Насчет второго вопроса - я Ваши объяснения не совсем понял.. :oops: Вы не могли бы статейку посоветовать, или хотя бы по каким ключевым словам искать?

Что именно? Про неявную передачу параметра? или про частичную параметризацию?

Частичная параметризация, partial parametrization, currying, parameter currying, haskel.

В ограниченном виде присутствует в Python.

 Профиль  
                  
 
 
Сообщение12.01.2006, 19:30 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Вот это:
незванный гость писал(а):
Поэтому, если я помню правильно, обычно делается статическая функция в классе, а ссылка на экземпляр сохраняется как пользовательский параметр dwRefData. Все, что делает статическая функция - typecast(dwRefData)->rightmethod(...).


Что за пользовательский параметр? Это параметр, передаваемый в статическую функцию? И как он в эту функцию передается?

 Профиль  
                  
 
 
Сообщение12.01.2006, 19:38 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Я имел в виду
Код:
BOOL SetWindowSubclass(          HWND hWnd,
    SUBCLASSPROC pfnSubclass,
    UINT_PTR uIdSubclass,
    DWORD_PTR dwRefData
);
[in] DWORD_PTR to reference data. This value is defined by the caller. This subclass stores one reference data item for each subclass callback.

Код:
LRESULT (CALLBACK *SUBCLASSPROC)(          HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam,
    UINT_PTR uIdSubclass,
    DWORD_PTR dwRefData
);

По-моему, это наиболее типовая ситуация. Если у Вас другая, я Вас не понял, виноват.

Пользовательский параметр dwRefData передается в Виндузе вместе с calback'ом. Виндузе хранит его, но никак не использует, за исключением одного случая -- передачи в callback при вызове оного.

 Профиль  
                  
 
 
Сообщение12.01.2006, 20:07 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Очень похоже на мою... Но...
Вы лучше, скажите, откуда Вы это взяли? Если из helpa на винду, то попробую сам поискать, если из хелпа на MFC, то посмотрим там...

Дело в том, что в "оконная процедура", которая вызывается для обработки сообщений окна принимает всего 4 параметра:
Код:
LRESULT CALLBACK WindowProc(
    HWND hwnd,   // handle of window
    UINT uMsg,   // message identifier
    WPARAM wParam,   // first message parameter
    LPARAM lParam    // second message parameter
   );

Этот прототип функции я выдрал из helpа на WIN API... Кстати, в упомянутой мной книге (автор Фень Юань (Feng Yuan), "Программирование графики под Windows") что-то такое упоминается про пользовательский параметр, но то решение напоминает вход в 5-ти звездочный отель через форточку в туалете.. :) Я его попробую привести, счас книгу полистаю...

 Профиль  
                  
 
 
Сообщение12.01.2006, 20:18 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Не сказал бы, что Виндузе - пятизвездочный отель. Скорее трущобы...

Нет у WindowProc этого параметра. Для него приходится ползти через GetWindowLong(h, DWL_USER) (и, соответственно, SetWindowLong()). Еще тот кайф, согласен.

А смотрел я, как и положено, в MSDN.

 Профиль  
                  
 
 
Сообщение12.01.2006, 21:06 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
незванный гость писал(а):
:evil:
Не сказал бы, что Виндузе - пятизвездочный отель. Скорее трущобы...


Не, я бы хотел, что б моя библиотека классов на него (отель) смахивала... :) Хотя возводить отели из того материала, что можно в трущобах найти - занятие неблагодарное... :(

Вот реализация, что я в книжке нашел...
Объявление класса:
Код:
class KWindow
{
protected:
   virtual void OnDraw(HDC hDC)
   {
   }
   virtual void OnKeyDown(WPARAM wParam, LPARAM lParam)
   {
   }   
   virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
   virtual void GetWndClassEx(WNDCLASSEX & wc);
   static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);   
   HRESULT CommonMDIChildProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
      HMENU hMenu, int nWindowMenu);
   HPALETTE m_hPalette;
   int       m_nUpdateCount;
   virtual LRESULT OnQueryNewPalette(void);
   virtual LRESULT OnPaletteChanged(HWND hWnd, WPARAM wParam);
   bool    m_bMainWindow;
public:
   HWND  m_hWnd;
   KWindow(void)
   {
      m_hWnd         = NULL;
      m_hPalette      = NULL;
      m_nUpdateCount = 0;
      m_bMainWindow  = false;
   }
   virtual ~KWindow(void)
   {
      if ( m_hPalette )
      {
         DeleteObject(m_hPalette);
         m_hPalette = NULL;
      }
   }   
   virtual bool CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, DWORD dwStyle,
      int x, int y, int nWidth, int nHeight, HWND hParent, HMENU hMenu, HINSTANCE hInst);
   bool RegisterClass(LPCTSTR lpszClass, HINSTANCE hInst);
   virtual WPARAM MessageLoop(void);
   BOOL ShowWindow(int nCmdShow) const
   {
      return ::ShowWindow(m_hWnd, nCmdShow);
   }
   BOOL UpdateWindow(void) const
   {
      return ::UpdateWindow(m_hWnd);
   }
};


Я приведу реализацию только двух функций - WndProc и WindowProc, думаю этого достаточно:

Код:
// Default message handler for main program window, dispatch to OnKeyDown, OnDraw, etc.
LRESULT KWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   switch( uMsg )
   {
      case WM_KEYDOWN:
         OnKeyDown(wParam, lParam);
         return 0;
      case WM_PAINT:
        {
            PAINTSTRUCT ps;                 
            BeginPaint(m_hWnd, &ps);
            OnDraw(ps.hdc);
            EndPaint(m_hWnd, &ps);
        }
        return 0;
      case WM_PALETTEISCHANGING: // should not happen
         MessageBox(NULL, _T("Hello"), _T("Hi"), MB_OK);
         return 0;
      case WM_PALETTECHANGED:
         return OnPaletteChanged(hWnd, wParam);
      case WM_QUERYNEWPALETTE:
         return OnQueryNewPalette();
      case WM_DESTROY:
         if ( m_bMainWindow )
            PostQuitMessage(0); // main window only
         return 0;
   }
   return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

// Generic window procedure passed to WIN32 API, dispatches to KWindow::WndProc
LRESULT CALLBACK KWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   KWindow * pWindow;
       
   if ( uMsg==WM_NCCREATE )
   {   
      assert( ! IsBadReadPtr((void *) lParam, sizeof(CREATESTRUCT)) );
      MDICREATESTRUCT * pMDIC = (MDICREATESTRUCT *) ((LPCREATESTRUCT) lParam)->lpCreateParams;

      pWindow = (KWindow *) (pMDIC->lParam);

      assert( ! IsBadReadPtr(pWindow, sizeof(KWindow)) );
      SetWindowLong(hWnd, GWL_USERDATA, (LONG) pWindow);
   }
   else
      pWindow=(KWindow *)GetWindowLong(hWnd, GWL_USERDATA);

   if ( pWindow )
      return pWindow->WndProc(hWnd, uMsg, wParam, lParam);
   else
      return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


Да, setwindowslong & getwindowsling, но мало того - указатель pwindow тока один раз передается - при создании окна... Криво, елки-палки, я думал - есть решения получше...

 Профиль  
                  
 
 
Сообщение12.01.2006, 22:32 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Да, вот еще... В с вязи с разговором о винде, вспомнилось-придумалось:
"Ну что, ребята, лайф не в кайф?" - с улыбкой подумал Билл Гейтс о программистах, пытавшихся использовать OLE 2.0... :)

 Профиль  
                  
 
 это от задачи зависит
Сообщение21.01.2006, 20:40 


02/08/05
55
никогда не использую ни стековых обьектов ни классов ни множественного наследования. прочитал в свое время книгу Галявова и до сих пор хватает. качество кода- чем проще и быстрее тем лучше. впрочем тут адепты VC6 а у меня пятый Борланд. скорость у него примерно та же.

 Профиль  
                  
 
 Re: это от задачи зависит
Сообщение21.01.2006, 21:04 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
вв писал(а):
прочитал в свое время книгу Галявова и до сих пор хватает. качество кода- чем проще и быстрее тем лучше.

Абсолютно согласен. Пока хватает -- все в порядке, чего изголяться-то.

 Профиль  
                  
 
 Re: это от задачи зависит
Сообщение22.01.2006, 14:18 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
вв писал(а):
качество кода- чем проще и быстрее тем лучше.


С этим трудно не согласится... :) Но я в последнее время на первое место ставлю

а) легкость модификации кода.
б) его безопасность (т.е. опечатки в идеале должны приводить к ошибкам компиляции, а не к ошибкам времени выполнения :) )
в) возможность повторного использования в других проектах.

т.е на мой взгляд, помимо хорошей реализации должна быть хорошая структура. :)

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

 Профиль  
                  
 
 Re: это от задачи зависит
Сообщение22.01.2006, 22:53 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Sanyok писал(а):
а) легкость модификации кода.
б) его безопасность (т.е. опечатки в идеале должны приводить к ошибкам компиляции, а не к ошибкам времени выполнения :) )
в) возможность повторного использования в других проектах.

Это все потому, что Вам важнее внешнии по отношению к программе качества. Из любимого щенка программа стала превращаться в тягловую лошадь (о которой заботятся, но которая в первую очередь работает). Просто профессиональное отношение. Кончились золотые студенческие годы :( :lol: . Вас начала интересовать цена разработки -- хотя бы в виде личного времени.

 Профиль  
                  
 
 Re: это от задачи зависит
Сообщение22.01.2006, 23:34 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
незванный гость писал(а):
Просто профессиональное отношение. Кончились золотые студенческие годы :( :lol: . Вас начала интересовать цена разработки -- хотя бы в виде личного времени.

Нет, просто старый стал и в конец обленился... :) Лень по десять раз переписывать одно и то же.. Что ни делаешь - ощущение, что делаешь это уже в десятый раз... А делать то же самое десятый раз - скучно. Поэтому, прежде чем сесть, десять раз подумаешь, как это сделать так, что бы потом можно было не переделывать и использовать как можно ширше.. :)

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 30 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group