Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Почему выдается ошибка 'theApp' : undeclared identifier  (Прочитано 11101 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« : 01-07-2010 07:06 » new

Подскажите, почему выдаётся ошибка 'theApp' : undeclared identifier.
Пример взяла из книги, который демонстрирует возможные способы доступа и общения между классами.
Фрейм - документ - представление.
Проект прикрепляю в том объёме, каком вы меня учили.
Да, книга использует С++ Visual 2005, а я Visual С++ 6.

* pr10.zip (17.03 Кб - загружено 1013 раз.)
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 01-07-2010 07:52 » 

Ну смотри:

1. Где она у тебя определена и задекларирована? (Подсказка: должна быть задекларирована в каком-нить .h файле и этот файл должен быть включен в .cpp)

2. Какова область видимости переменной theApp у тебя в проекте?

3. О чём говорит название ф-ции AfxGetApp()? Нельзя ли её использовать в твоём случае вместо theApp?

зы

Да, книга использует С++ Visual 2005, а я Visual С++ 6.

В данном случае разница непринципиальная. Даже VS 2010 показала ошибку Ага
« Последнее редактирование: 01-07-2010 08:17 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #2 : 01-07-2010 08:45 » 

Джон, Спасибо. Использовала AfxGetApp() - получила,что нужно было.
Потом нашла описание theApp в pr10.h. Тоже получилось.
Сколько времени на эту хрень потратила перед тем,как у вас спросить!
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 01-07-2010 11:02 » 

ann_nef, в любом месте программы можно сделать


extern CMyApp theApp;
theApp. ... ;

только ещё хидер с твоим классом CMyApp надо в начало файла заинклудить
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #4 : 01-07-2010 11:05 » 

Зато теперь на всю жизнь запомнишь. Обратный эффект получился бы, если бы ты сразу спросила и получила бы ответ, в виде решения.

Ну хоть поняла в чём дело было и как объявляются глабальные переменные? В чём разница между ф-ей AfxGetApp и глобальной переменной? Зачем она вобще нужна?

зы Вопросы просто для самоконтроля, отвечать ессно необязательно. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #5 : 01-07-2010 11:08 » 

Джон, в догонку.
Еще один способ описан в CMainFrame::OnMyFrame() (надо вставить в эту пп)

// Получить указатель представления
CPr10View *pView2 = (CPr10View  *)AfxGetApp()->GetRuntimeClass();
pView2->f_mess(6);         // Вывести сообщение представления

Но на экране это сообщение так и не появляется! Что не так?
Записан
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #6 : 01-07-2010 11:12 » 

Ой, ...f_mess().  6 - лишняя для 1 варианта пр-мы.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #7 : 01-07-2010 11:17 » 

ann_nef, тебе надо чётко представлять как устроена Doc-View-архитектура  MFC. Ты это представляешь? По каким учебникам занимаешься? И вобще, откуда черпаешь знания?

зы Это вопросы не на засыпку, мне просто нужно иметь представление о твоём уровне знаний, чтобы разговаривать (отвечать) на понятном языке.

зы зы Ты пойми меня правильно, совсем нетрудно исправить ошибки в твоей программе, но будет ли это помощью?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #8 : 01-07-2010 11:34 » 

Знания черпаю из "Visual Studio C++ и MFC. Самоучитель." Т.Сидориной.
Те, читаю и делаю задачи из этой книги. Доехала доехала до 10 главы из 15. Предыдущие главы были проще и знакомее, тк исп. только Frame-View, до этой книги в программе пользовалась только диалогом.
Представление об архитектуре документ/представление слабое:
Фрейм-представление-документ.
Так что, чем проще, тем лучше.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 01-07-2010 12:43 » 

Ок. Всё очень просто. Для оконного приложения нам нужно как минимум... окно. Это может быть диалог - контейнер для контролов, типа кнопок, комбобоксов и тд, или фрейм (рамка) - более продвинутый контейнер для других окон, которые могут например изменять свои размеры в пределах (будем называть его правильно) родительского окна.

С диалогами ты уже разобралась.

Фреймовые документы бывают двух типов (Multiple top-level Document отбрасываем и забываем, это извращение над MDI, и если мне не изменяет память в шестёрке такого ещё не было). Итак, двух типов - SDI и MDI. SDI (Single Document) подразумевает работу с одним экземпляром ДАННЫХ в рамках MainFrame. Например, с одим файлом типа TXT. Отличие MDI в том, что он может работать с множеством экземпляров одной модели данных. Но для понимания Doc-View это несущественно. Итак, вернёмся к SDI. Примером такого приложения может служить Блокнот. Ты открываешь (те инициаллизируешь внутреннюю структуру данными) файл и его содержимое отображается в окошке. Отсюда необходимость в двух объектах. Один отвечает за хранение данных - Document, другой отвечает за отображение этих данных - View.
Очевидно, что у одних и тех же данных, может быть несколько ВИДОВ (Views). Пример - Проводник винды. У него есть два вида одних и тех же данных - дерева каталогов и файлов. Обычно слева ты видишь эти данные в виде дерева, а справа в виде списка. Хотя это одна и таже информация.
Другой пример - представь у тебя есть некие столбцы данных. Ты можешь отображать их в виде таблицы и/или в виде графика. Причём эти ВИДЫ можно показывать по очереди (переключателем), или же одовременно - для этого используется элемент управления под названием Splitter (разделитель), который разделяет рамку на две части и предоставляет полученные части независимым ВИДАМ. Каждую такую рамку, в свою очередь можно также разделить на части и тд. Таким образом мы получаем целый список объектов View, в одном документе. И, соответственно, чтобы добраться до искомого, нам необходимо пробежаться по их списку. Для этого используются ф-ции объекта CDocument:

GetFirstViewPosition() - для получения адреса (позиции) первого ВИДА
GetNextView - для получения объекта по адресу.

Последняя возвращает указатель на объект, родительским классом которого является CView. Если тебе необходимо получить доступ к общим ф-ям этого объекта, то кастинг необязателен. Например:

Код:
   POSITION pos = GetFirstViewPosition();
   while (pos != NULL)
   {
      CView* pView = GetNextView(pos);
      pView->UpdateWindow();    // это ф-я объявленная в родительском классе CView
   }
   

Таким образом осуществляется, например, перерисовка всех ВИДОВ одного документа, при изменении данных.

Если же тебе нужен какой-то конкретный ВИД, то перед кастингом (приведением типа к какому-то конкретному значению - в твоём случае это CPr10View), необходимо сначала удостовериться, что полученный указатель является именно искомым объектом.

Ну в принципе ты уже делала нечто подобное, только с документами.

Код:
	POSITION post1 = AfxGetApp()->m_pDocManager->GetFirstDocTemplatePosition();  
CSingleDocTemplate *psdt1 =
(CSingleDocTemplate*)AfxGetApp()->m_pDocManager->GetNextDocTemplate(post1);
POSITION posd1 = psdt1->GetFirstDocPosition();
CPr10Doc *pdoc2 = (CPr10Doc *) psdt1->GetNextDoc(posd1);

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

Немного понятней стало?

А теперь ответь мне на вопрос, чего ты хотела добиться строчкой:
Код:
CPr10View *pView2 = (CPr10View *)AfxGetApp()->GetRuntimeClass();

и что именно делает ф-я GetRuntimeClass?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #10 : 02-07-2010 06:08 » 

Этой строчкой CPr10View *pView2 = (CPr10View *)AfxGetApp()->GetRuntimeClass();
я хотела добраться до указателя представления, чтобы потом вызвать пп сообщения представления.
(так в книге написано)
GetRunTimeClass возвращает информацию о классе , тоже что делает RUNTIME_CLASS.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #11 : 02-07-2010 11:31 » 

Сразу оговорюсь. Просто для понимания. То, что ты называешь "представлением", я называю "видом" - View.

Итак.

Правильно, ИНФОРМАЦИЮ о классе, а не сам объект. Это разные вещи. Одна - это описание класса, или типа данных. Другая - физическая инстанция, созданная в памяти структура, которая занимает определённые ресурсы. Тебе нужно второе. Его ты находишь как выше описано - пробигаешь по списку (ок!) ПРЕДСТАВЛЕНИЙ физического объекта типа CDocument. Указатель на него ты уже нашла - pdoc2.

Конечно, в твоём случае у тебя есть только ОДНО ПРЕДСТАВЛЕНИЕ, и ессно именно оно будет возвращено ф-ей GetNextView.
Поэтому, ты можешь сразу преобразовать тип CView к CPr10View. НО! Мы же хотим сделать всё правильно. Представь, что это обращение к объекту типа View зарыто глубоко в коде, и кто-то, работающий после тебя, добавляет ещё парочку, не подозревая о нём. Совершенно необязательно, что твой View окажется первым в списке. Тогда к типу CPr10View будет приведёт объект совершенно другой структуры. С++ это позволяет, указатели в С++ это большая сила и одновременно большая слабость языка. Слабость для тех, кто безалаберно с ними обращается. Это ты понять с самого начала и обращаться с указателями на "ВЫ".

Итак, мы хотим выяснить, какой объект вернула нам при очередной итерации ф-я GetNextView? Имеем ли мы право делать преобразование типа?

Цитата
GetRunTimeClass возвращает информацию о классе , тоже что делает RUNTIME_CLASS.

Это не совсем так.  Ф-я GetRunTimeClass вызывается у конкретного объекта, а макрос RUNTIME_CLASS получает в качестве параметра просто КЛАСС. Ему объект не нужен. Но нам нужен не абы какой, а именно CPr10View. Для этого и существет макрос RUNTIME_CLASS, который при выполнении определённых условий позволяет создать объект типа CRuntimeClass. Те проверка условия может быть такой:

Код:
if(pView->GetRuntimeClass() == RUNTIME_CLASS(CPr10View))

Но мы сделаем это немного элегантней.

Поскольку почти каждый MFC-объект является производным от родительского класса CObject, воспользуемся ф-ей IsKindOf этого класса.
Эта ф-я получает в качестве параметра объект типа CRuntimeClass.

Тогда поиск выглядит примерно так:

Код:
	CPr10View *pMyView = NULL;
POSITION pos = pdoc2->GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = pdoc2->GetNextView(pos);
if(pView->IsKindOf(RUNTIME_CLASS(CPr10View)))
{
pMyView = (CPr10View*)pView;
break;
}
}

if(pMyView)
{
pMyView->f_mess();
}
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines