Анимация
JavaScript
|
Главная Библионтека char buf[80]; /* = */ win->GetWindowText(buf, sizeof(buf)); ... Так как я должен выполнить инициализацию при помощи явного вызова функции, то умышленно нарушаю свое правило "один оператор в строке" для того, чтобы, по крайней мере, вместить объявление и инициализацию в одной и той же строке. Здесь имеется несколько проблем, первая из которых заключается в плохом проектировании класса CWnd (представляющем окно). Так как у окна есть " текстовый" атрибут, хранящий заголовок, то вы должны иметь возможность доступа к этому атрибуту подобным образом: CString caption = win->caption(); и вы должны иметь возможность модифицировать этот атрибут так: win->caption() = " новое содержание"; но вы не можете сделать этого в текущей реализации. Главная проблема состоит в том, библиотека MFC не была спроектирована в объектно-ориентированном духе - т. е. начать с объектов, затем выбрать, какие static int have been called = 0; if( !have been called ) have been called = 1; do one time initializations(); 134. Избегайте инициализации в два приема 1 35. Суперобложки на Си++ для существующих интерфейсов редко хорошо работают Как правило, переменная должна инициализироваться во время объявления. Разделение инициализации и объявления иногда обусловливается плохим проектированием в программе, которая написана не вами, как в следующем фрагменте, написанном для выполнения совместно с библиотекой MFC Microsoft: f( CWnd *win ) CWnd - это окно Следующая строка загружает "буфер" с шапкой окна (текстом в строке заголовка) сообщения передавать между ними и какими атрибутами их наделить. Вместо этого проектировщики Microsoft начали от существующего процедурного интерфейса (API Си - интерфейса прикладного программирования для Windows на Си) и добавили к нему суперобложку на Си++, тем самым увековечив все проблемы существующего интерфейса. Так как в API Си была функция с именем GetWindowText(), то проектировщики беззаботно сымитировали такой вызов при помощи функции-члена в своей оболочке CWnd. Они поставили заплату на интерфейс при помощи следующего вызова: CString str; win->GetWindowText( str ); но это - не решение по двум причинам: по-прежнему требуется инициализация в два приема, и аргумент является ссылкой на результат. Главный урок состоит в том, что проекты, основанные на процедурном подходе, радикально отличаются от объектно-ориентированных проектов. Обычно невозможно использовать код из одного проекта в другом без большой переработки. Простая оболочка из классов Си++ вокруг процедурного проекта не сделает его объектно-ориентированным. Поучительно, я думаю, пошарить вокруг в поисках решения текущей проблемы с помощью Си++, но предупреждаю вас - здесь нет хорошего решения (кроме перепроектирования библиотеки классов). Моя первая попытка сделать оболочку вокруг CWnd показана на листинге 11. Для обеспечения возможности win->text() = "Новый заголовок" необходим вспомогательный класс (window::caption). Вызов text() возвращает объект заголовка, которому затем передается сообщение присваиванием. Главная проблема на листинге 11 заключается в том, что библиотека MFC имеет много классов, унаследованных от CWnd, и интерфейс, реализованный в классе window, не будет отражен в других потомках CWnd. Си++ является компилируемым языком, поэтому нет возможности вставлять класс в середину иерархии классов без изменения исходного кода. Листинг 1 2 определяет другое решение для смеси Си++ с MFC. Я выделил класс window::caption в отдельный класс, который присоединяется к окну, когда оно инициализируется. Используется подобным образом: f(CWnd *win) caption cap( win ) CString s = cap; поддерживается преобразование в CString. cap="Новый заголовок"; использует операцию operator=(CString&) Мне не нравится то, что изменение заголовка caption меняет также окно, к которому этот заголовок присоединен в этом последнем примере. Скрытая связь между двумя объектами может сама по себе быть источником недоразумений, будучи слишком похожей на побочный эффект макроса. Как бы то ни было, листинг 1 2 решает проблему инициализации. Листинг 11. Обертка для CWnd: первая попытка I class window : public CWnd 2{ 3 public: 4 class caption 5{ 6 CWnd *target window; 8 private: friend class window; 9 caption( CWnd *p ) : target window(p) {} II public: 12 operator CString ( void ) const; 13 const caption &operator=( const CString &s ); 14 }; 16 caption text( void ); 17 }; 18 --------------------------------------------------------19 caption window::text( void ) 20 { 21 return caption( this ); 22 } 23 --------------------------------------------------------24 window::caption:: operator CString( void ) const 25 { 26 CString output; 27 target window->GetWindowText( output ); 28 return output; возвращает копию 29 } 30 --------------------------------------------------------31 const caption &window::caption::operator=(const CString &s) 32 { 33 target window->SetWindowText( s ); 34 return * this; 35 } 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 [ 61 ] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |