Перейти к содержанию
    

Visual C++. Основа основ.

CButton* pMyButton1 = GetDlgItem(IDC_Button1);
pMyButton1->SetWindowText("My New Button");

Это противоречие Вашим собственным словам и моя проблема на первом этапе пользования вижака. Чтобы достучаться до объекта, который уже создан, я должен зачем-то вызывать какую-то непонятную функцию по идентификатору! С ОО это не имеет ничего общего и с пониманием ОО тоже.

Никакого противоречия ! Функция GetDlgItem(...) - это тоже метод класса Вашего диалога, из которого Вы её вызываете! Перепишем для ясности

CButton* pMyButton1 = this->GetDlgItem(IDC_Button1);
pMyButton1->SetWindowText("My New Button");

И ещё. Я же писал, что идентификаторами можно и не пользоваться. Заведите себе в классе Вашего диалога кнопку

CButton MyButton;

и общайтесь с ней без всяких идентификаторов

MyButton.SetWindowText("My first button");

Это вопрос стиля программирования. Мне, например, удобнее заводить идентификаторы для объектов, и если им раздать осмысленные имена - программа становится удобочитаемой...

 

Во вторых, Вы обращали внимание, что среди членов того или иного класса в основном одни только функции (SetWindowText, AddString, и пр.)? Как таковых свойств или полей-переменных нет почти. Я лично не верю, что их нет на самом деле. Почему бы не сделать, например

pMyButton1->Text = "My New Button";

?

Это конечно может придирки, но мое мнение, что закрытие этих членов, доступ к ним только через функции - долбанутая политика MS по части безопасного кода. От кого их скрывать? От разработчика? А то что их якобы как бы вовсе нет (все реализуется через функции) - я не верю - в таком случае, чтобы сделать банальную перерисовку надо на ежа сесть.

Вот. Это и есть образ мышления программиста, привыкшего к статическому программированию ! Так было, когда программисты хранили данные в структурах и обращались к ним по имени полей. И опять летят камни в адрес Microsoft ...

На самом деле MS тут ни при чём. Вы затронули один из краеугольных камней ООП, именуемый инкапсуляцией - это не только объединение кода и данных внутри объекта, как думают многие начинающие программеры. Это ещё и разделение интерфейса и реализации объекта (public, protected, private), а также сокрытие реализации, но не от разработчика, а от ошибок. Рассмотрим Ваш пример внимательнее.

pMyButton1->Text = "My New Button";

Это аварийный код по определению. Объясню почему.

1. Что за поле Text ? Если это указатель на строку, то его содержание будет утеряно, как только будет разрушена константа "My New Button" - и это произойдёт по выходу из локальной функции. Будет ошибка доступа к памяти.

2. Если это объект класса CString, то не надо заниматься самообманом - за оператором присваивания = стоит работа тех же методов класса CString, которые скопируют Вашу константу к себе в "недра".

3. А как Вы узнали при присваивании, что хватит памяти для Вашей строки ?

4. А Вы уверены, что поле Text есть внутри ?

 

В том то и дело, что прямой доступ к данным внутри объекта всегда чреват разрушением объекта из-за несоответствия данных размерам памяти. И вообще, динамическое программирование подразумевает, что память под данные (возможно, гигантского объёма) выделяется и освобождается динамически, и никогда "снаружи" класса неизвестно, сколько памяти и для чего уже выделено внутри объекта. Об этом "знает" только сам объект и поэтому он сам рулит менеджментом внутри, а снаружи только интерфейс из функций. Так что это не "бага" - это "фича", это надо прочувствовать, прелесть того, что ты не обязан помнить, какой длины массив у тебя, и ты всегда можешь безопасно добавить в него ещё один элемент !!!

 

Почитайте, например, в нем о том как назначить группу RadioButton-у (CRadioButton, если не запамятовал). Я смеялся и плакал.

Я всегда это делал путём установки галочки прямо в редакторе ресурсов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Demeny,

здесь

pMyButton1->Text = "My New Button";

судя по всему подразумевалось "свойство", а не просто переменная-член, так что с точки зрения ООП тут все путем - это просто "сокращенная" форма записи вызова метода

pMyButton1->SetText("My New Button");

, активно используемая сугубо борландовским компилятором, как расширение в C++.

IMHO польза от такого расширения минимальна, зато вред (в плане переносимости) очевиден.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Функция GetDlgItem(...) - это тоже метод класса Вашего диалога, из которого Вы её вызываете!

 

Спасибо, разъяснили.

 

Вот. Это и есть образ мышления программиста, привыкшего к статическому программированию ! Так было, когда программисты хранили данные в структурах и обращались к ним по имени полей. И опять летят камни в адрес Microsoft ...

На самом деле MS тут ни при чём. Вы затронули один из краеугольных камней ООП, именуемый инкапсуляцией - это не только объединение кода и данных внутри объекта, как думают многие начинающие программеры. Это ещё и разделение интерфейса и реализации объекта (public, protected, private), а также сокрытие реализации, но не от разработчика, а от ошибок. Рассмотрим Ваш пример внимательнее.

 

pMyButton1->Text = "My New Button";

 

Это аварийный код по определению. Объясню почему.

1. Что за поле Text ? Если это указатель на строку, то его содержание будет утеряно, как только будет разрушена константа "My New Button" - и это произойдёт по выходу из локальной функции. Будет ошибка доступа к памяти.

2. Если это объект класса CString, то не надо заниматься самообманом - за оператором присваивания = стоит работа тех же методов класса CString, которые скопируют Вашу константу к себе в "недра".

3. А как Вы узнали при присваивании, что хватит памяти для Вашей строки ?

4. А Вы уверены, что поле Text есть внутри ?

 

В том то и дело, что прямой доступ к данным внутри объекта всегда чреват разрушением объекта из-за несоответствия данных размерам памяти. И вообще, динамическое программирование подразумевает, что память под данные (возможно, гигантского объёма) выделяется и освобождается динамически, и никогда "снаружи" класса неизвестно, сколько памяти и для чего уже выделено внутри объекта. Об этом "знает" только сам объект и поэтому он сам рулит менеджментом внутри, а снаружи только интерфейс из функций. Так что это не "бага" - это "фича", это надо прочувствовать, прелесть того, что ты не обязан помнить, какой длины массив у тебя, и ты всегда можешь безопасно добавить в него ещё один элемент !!!

 

Спасибо за обстоятельное пояснение. :a14:

 

...а также сокрытие реализации, но не от разработчика, а от ошибок.

 

Понимаю: разработчик - причина ошибок. ;)

 

Со строковым полем это я конечно загнул - последствия борланда, но с переменными типа int, например, ситуация не лучше. А что касается безопасного кода, это конечно словоблудие, философия, но кто ответит за баг в мое программе, возникающий по причине того, что MS чего-то там намутили? Любая кажущаяся простота упирается как правило в расслабленность программиста. Тем не менее, фичу прочувствовал! :glare: Вот только ирония в мозгах возникает (это не про Вас) - многие из тех кто програмят на MFC они еще про динамические структуры дальше указателя на переменную чего-нибудь помнят\знают? :)

 

здесь

pMyButton1->Text = "My New Button";

судя по всему подразумевалось "свойство", а не просто переменная-член, так что с точки зрения ООП тут все путем - это просто "сокращенная" форма записи вызова метода

pMyButton1->SetText("My New Button");

, активно используемая сугубо борландовским компилятором, как расширение в C++.

 

Согласен, так оно и есть.

 

IMHO польза от такого расширения минимальна, зато вред (в плане переносимости) очевиден.

 

IMHO в случае написания под конкретный GUI в конкретной среде разработки не о какой переносимости речи вообще не может идти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

IMHO в случае написания под конкретный GUI в конкретной среде разработки не о какой переносимости речи вообще не может идти.
Тогда зачем связываться с VC++? Чем билдер не устроил?

Многие из тех кто програмят на MFC они еще про динамические структуры дальше указателя на переменную чего-нибудь помнят\знают?
Что вы понимаете под "динамической структурой"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И что немаловажно - хорошо задокументированы. Читайте MSDN - откроете много интересного...

 

Сам VC вестчь полезная, не спорю. Можно писать очень элегантные проги, многие поймут о чем говорю. На их система справки - кал. По объему - библия программирования для винды, по по удобству работу - кал и еще раз кал. Мне однажды даже пришлось установить Билдер, чтобы работать с их хелпером, который является во многих местах очень удобной копией, причем рабоей копией. А в MSDN я находил дыры - элементарные ссылки, на несуществующие страницы (msdn апрель 2001 года), причем по законам Мерфи эти несуществующие страницы были самыми нужными, а VC6.0 была лицензионной софтиной . Стыдно! А еще добавьте объем их chm-файлов, можно и поудобнее было выбрать. А если попробуете спорить, то вот вам туз из рукава - пункт контекстного меню "Закрыть". Сама Microsoft сделала почти стандартом, что этот пункт последний в меню (кликните правой кнопкой на програмке в панели задачь), а у этих гребаных chm-ов - там хелп (about). И только ни говорите мне, что никто на автопилоте не выбирал этот пункт вместо желанного "Закрыть"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно работать так же как и в Билдере. Тока менее удобно получается (писанины больше, ошибок может быть больше, проверок надо больше).

 

MFC. Допустим, есть ListBox, Button и Edit. По клику на Button берем то что в Edit и добавляем в ListBox (при этом ListBox скроллим вниз доконца).

Обработчик нажатия на кнопку генерится в VS, и код может выглядеть так:

CString s;
GetDlgItemText(IDC_EDIT1, s);
((CListBox *) GetDlgItem(IDC_LIST1))->AddString(s);
((CListBox *) GetDlgItem(IDC_LIST1))->SetCurSel(((CListBox *) GetDlgItem(IDC_LIST1))->GetCount() - 1);

 

При этом не заводятся переменные, и не нужен этот нанавистный UpdateData(). Собстно, пишу почти все так (без добавленяи каких-либо переменных для рбаоты через DDX). Все отлично работает и ИМХО удобнее, но длинно....

 

Хелп замечательно сделан. Тока пользоваться надо уметь ;)

Изменено пользователем SysRq

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...