Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Методические указания. Сценарий создания приложения




Сценарий создания приложения

M_wndStatusBar.SetPaneInfo(1, 0, SBPS_STRETCH, 50);

M_wndStatusBar.SetPaneInfo(0, 0, 0, 50);

 

Узнайте назначение параметров SetPaneInfo() из MSDN. Проверьте, что теперь строка состояния ведет себя подобающим образом.

 

Шаг 14. Добавьте вывод координат мыши в строку состояния. Для этого присовокупите сначала к классу вида обработчик сообщения WM_MOUSEMOVE и наполните его таким кодом:

 
 

 

Соберите и тестируйте приложение. Не получается? В чем проблема? Попробуйте сами устранить ошибки. Если не получится – станьте на голову и прочтите ценные указания.

 

 
 

 

Боевое задание для совершения подвига. В нынешнем виде программа открывает для просмотра файлы только с расширениями.bmp,.jpg,.gif и.png, хотя система поддерживает большее число форматов. Вам предоставляется возможность расширить функциональность программы, научив ее открывать и файлы других графических форматов. Найдите в MSDN описание функции CImage::GetExporterFilterString() и … Вы сможете решить эту проблему. Убедитесь в том, что программа корректно сохраняет открытый файл любого формата. Для этого, очевидно, Вам понадобится отредактировать текст функции CChildView::OnSaveimage(). Вообще говоря, было бы уместно передать перечень типов файлов, возвращаемых функцией CImage::GetExporterFilterString(), в функцию CChildView::OnSaveimage().


12. Разработка приложения с архитектурой «документ-вид». Часть 1

Невозможно создать программу с полной защитой от дураков, ибо дураки крайне изобретательны

Закон Мерфи

Цель работы – освоить разработку приложения, основанного на архитектуре «документ-вид» (4 час.)

Сценарий этой работы основан на материале глав 16 и 17 работы [1]. Характерной особенностью этого приложения является не только его ориентация на архитектуру «документ-представление», но и использование класса CFormView в качестве базового для окна вида.

Суть работы состоит в следующем. Создается каркас SDI-приложения с архитектурой «документ-вид» и в качестве базового класса для класса представления выбирается CFormView. Этот класс подобен классу CDialog в том смысле, что он может быть носителем управляющих элементов: полей ввода, переключателей, списков и т.п. – в отличие от базового класса CView. На следующем шаге Вы должны разработать свой собственный класс, предназначенный для обработки некоторых данных, отличающийся от описанного ниже класса CStudent количеством и типами компонент. В качестве примера в данном сценарии приводится класс CStudent, который содержит только фамилию студента и целочисленный балл. Далее необходимо разместить в окне представления управляющие элементы, предназначенные для ввода (и отображения) данных и реализовать сохранение введенных данных в классе документа.

Задание.

1. Ознакомьтесь с теоретической частью работы по конспекту лекций (разделы 9, 5.3-5.5).

2. Создайте приложение в соответствии с приведенным ниже сценарием. Разработайте свой собственный класс и, соответственно, свои управляющие элементы для ввода данных.

3. Выполните отладку и добейтесь работоспособности приложения.

4. Осмыслите полученный результат, примененный инструментарий и приемы программирования.

5. Ответьте на коварные вопросы преподавателя и получите наивысшую оценку. Если удастся продать свое приложение (а за ним уже давно гоняются шпиёны из Microsoft) – поделитесь доходами с кафедрой, например, купите хотя бы один новый компьютерный класс.

 

 

Шаг 1 (решительный). Создание каркаса приложения.

Создайте новый проект, присвойте ему имя, выберите Project types=MFC и Templates=MFC Application. В данном сценарии я выбрал для проекта незамысловатое, т.е. гениальное, имя FRM. Придавите ОК. На вкладке Application type:

· шлепните по радиокнопке Single document;

· слегка щелкните по радиокнопке MFC Standard;

· в списке Resource language не забудьте выбрать элемент со значением Русский;

· установите переключатель Use Unicode libraries.

 

Значения остальных свойств не изменяйте под страхом смерти, т.е. незавершения отладки приложения при жизни.

Перейдите к вкладке Generated Classes и для класса представления CFRMView выберите в качестве базового класс CFormView вместо коварно предлагаемого по умолчанию класса CView (рис. 1). Завершите создание каркаса приложения торжественным шлепком по кнопке Finish. Постройте и запустите приложение на выполнение, чтобы посмотреть на его внешний вид. Окно вида напоминает диалоговое окно, но вместе с тем в нем присутствует меню и панель инструментов, что не может не радовать, так как досталось даром.

 

Шаг 2. Добавление в приложение собственного класса.

Свой собственный класс проще всего добавить в проект с помощью команды меню ProjectèAdd class, в результате выполнения которой появится диалоговое окно, посредством которого Вы и сможете создать свой класс. В этом окне выберите Categories=MFC и Templates=MFC Class и нажмите кнопку Add. В другом появившемся окне выберите в качестве базового (Base class) класс CObject и задайте имя своего класса, например, CStudent. Обратите внимание, что мастер предлагает имена файлов Student.h и Student.cpp, в которых будет располагаться объявление класса и его реализация соответственно. Если не боитесь проклятий возможных читателей вашего проекта – изменяйте имена файлов. Нажмите Finish, если не страшно.

 

 
 

Рис. 1. Выбор базового класса CFormView для класса вида CFRMView

 

Вы могли бы изменить имена файлов, сгенерированные мастером, но я бы этого не рекомендовал.

Файлы Student.h и Student.cpp добавлены в проект, но файл Student.h пока никуда не подключается с помощью директивы препроцессора include – это надо будет впоследствии сделать вручную, так как мастер не может догадаться, где мы собираемся использовать данный класс.

Содержимое файлов Student.h и Student.cpp должно быть таким:

// Файл Student.h #pragma once // CStudent command target class CStudent: public CObject { public: CStudent(); virtual ~CStudent(); };  
// Student.cpp: implementation file // #include "stdafx.h" #include "FRM.h" #include "Student.h" // CStudent CStudent::CStudent() { } CStudent::~CStudent() { } // CStudent member functions  

 

Шаг 3. Добавление членов в класс CStudent.

Для того чтобы класс CStudent был полезен, надо добавить в него член-данные, парочку конструкторов и функцию Dump, предназначенную для вывода отладочной информации. Кроме того, добавьте в файлы макросы DECLARE_DYNAMIC и IMPLEMENT_DYNAMIC, которые гарантируют, что имя класса будет доступно при выводе диагностической информации. Модифицируйте файлы Student.h и Student.cpp в соответствии с приведенными ниже листингами.

// Файл Student.h

#pragma once

class CStudent: public CObject

{

DECLARE_DYNAMIC(CStudent)

public:

CString m_strName; // фамилия студента

int m_nGrade; // отметка

CStudent(); // конструктор по умолчанию

CStudent(const char* szName, int nGrade); // конструктор с параметрами

virtual ~CStudent();

#ifdef _DEBUG

void Dump(CDumpContext& dc) const;

#endif // _DEBUG

};

 

 

 

// Student.cpp: implementation file

#include "stdafx.h"

#include "FRM.h"

#include "Student.h"

// CStudent

IMPLEMENT_DYNAMIC(CStudent, CObject)

CStudent::CStudent()

{

m_nGrade = 0;

}

CStudent::CStudent(const char* szName, int nGrade)

{

m_strName = szName;

m_nGrade = nGrade;

}

 

CStudent::~CStudent()

{

}

// CStudent member functions

#ifdef _DEBUG

void CStudent::Dump(CDumpContext& dc) const

{

CObject::Dump(dc);

dc << "m_strName = " << m_strName << "\nm_nGrade = " <<m_nGrade;

}

#endif // _DEBUG

 

Убедитесь в том, что приложение компилируется без ошибок, невзирая на Ваши старания по его усовершенствованию.

Шаг 4. Редактирование меню приложения.

Оставим пока класс CStudent и займемся интерфейсом программы. На вкладке Resource View выберите идентификатор IDR_MAINFRAME в ветви Menu и, незаметно для ИС, замените имеющиеся команды в меню Правка на единственную команду Clear АLL. Введите константу ID_EDIT_CLEARALL как идентификатор команды Clear АLL (см. вкладку Properties).

 

Шаг 5. В редакторе диалоговых окон измените диалоговое окно IDD_FRM_FORM. Открыв диалоговый ресурс IDD_FRM_FORM в ветви Dialog, сгенерированный мастером, добавьте элементы управления для ввода имени студента и целочисленного балла (рис. 2). Не изменяйте установленных по умолчанию свойств формы Style=Child и Visible=False.

 
 

Рис. 2. Окно представления с управляющими элементами

 

Присвойте элементам управления идентификаторы, указанные табл. 1.

Таблица 1.

Элемент управления ID
Элемент ввода фамилии IDC_NAME
Элемент ввода отметки IDC_GRADE
Кнопка «Принять» IDC_ENTER

 

Шаг 6. Добавьте обработчики сообщений для CFRMView. Выберите класс CFRMView (вкладка Class View) и добавьте указанные ниже обработчики сообщений (табл. 2). Оставьте имена функций по умолчанию.

Таблица 2.

Идентификатор ресурса Сообщение Обработчик сообщения
IDC_ENTER BN_CLICKED OnBnClickedEnter
ID_EDIT_CLEARALL COMMAND OnEditClearall
ID_EDIT_CLEARALL UPDATE_COMMAND_UI OnUpdateEditClearall

 

Шаг 7. Добавьте переменные для CFRMView.

Добавьте для элементов ввода Фамилии и Отметки студента переменные, свойства которых приведены в табл. 3. Напомню, что для добавления таких переменных надо в окне редактора ресурсов выбрать элемент ввода, с помощью ПКМ вызвать контекстное меню и в нем выбрать команду Add variable.

Таблица 3.

Идентификатор ресурса Имя переменной Категория Тип переменной
IDC_GRADE m_nGrade Value int
IDC_NAME m_strName Value CString

 

Задайте для m_nGrade минимальное значение 0, максимальное — 100. Заметьте, что мастер генерирует код, необходимый для проверки данных, вводимых пользователем (найдите этот код).

 

Шаг 8. Добавьте прототип вспомогательной функции UpdateControlsFromDoc. В окне ClassView выберите класс CFrmView щелкните ПКМ и выберите команду AddèAdd Function (добавить функцию-член). Заполните диалоговую форму, чтобы добавить следующую функцию:

private:

void UpdateControlsFromDoc();

 

Шаг 9. Отредактируйте файл FRMView.cpp. Отредактируйте код функций так, как показано ниже:

 
 

 

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

Функция OnBnClickedEnter() заменяет функцию OnOK(), которую можно было бы ожидать в классе диалогового окна. Она передает данные из полей ввода в переменные-члены объекта «вид», а потом в документ. Добавьте код, выделенный полужирным шрифтом:

 
 

 

В сложной программе, допускающей несколько представлений данных, команда Clear All передавалась бы непосредственно документу. В нашем же простом примере она доставляется объекту «вид». Обработчик сообщения обновления пользовательского интерфейса отключает элемент меню, если объект CStudent в документе уже пуст. Договоримся, что объект будет считаться пустым, если член m_nGrade==0. Отредактируйте обработчики команды меню в соответствии со следующим листингом:

 
 

 

Шаг 10. Добавьте переменную типа CStudent в класс CFRMDoc. Это можно сделать, используя окно ClassView и контекстное меню, тогда директива #include “Student.h”будет добавлена автоматически.

public: CStudent m_student;

 

Вот теперь приложение должно компилироваться, хотя у компилятора может быть и свое мнение по этому поводу.

Конструктор класса CStudent вызывается при создании объекта «документ», а деструктор вызывается автоматически при уничтожении документа.

Шаг 11. Отредактируйте файл FRMDoc.cpp. Для инициализации объекта CStudent воспользуйтесь конструктором CFRMDoc:

CFRMDoc::CFRMDoc(): m_student("", 0){ TRACE("Document object constructed\n");}

 

Мы не определим, правильно ли работает программа FRM, пока не выведем содержимое документа по завершении программы. Для этого воспользуемся деструктором, который вызовет функцию Dump() документа, а та — функцию CStudent::Dump(). А посему отредактируйте код деструктора класса документ и функции Dump() этого же класса. Вы, конечно, заметили, что функция Dump(afxDump) будет вызываться только в отладочной конфигурации приложения, так как ее вызов окружен директивой условной компиляции #ifdef _DEBUG … #endif.

 
 

 

Шаг 12. Соберите и протестируйте приложение FRM. Введите какое-нибудь имя и балл, а затем щелкните кнопку Принять. Закройте приложение. Появились ли в окне Debug сообщения, аналогичные показанным ниже?

a CFRMDoc at $00358FF0m_strTitle = _CrtDbgReport: String too long or IO Errorm_strPathName = m_bModified = 0m_pDocTemplate = $00358DF8 a CStudent at $00359044m_strName = Smithm_nGrade = 34

 

Примечание. Чтобы увидеть эти сообщения, компилируйте программу для конфигурации Debug и запустите ее под управлением отладчика (F5, а не Ctrl+F5).

 

Некоторые пояснения к строке

m_strTitle = _CrtDbgReport: String too long or IO Error

В ней выводится заголовок окна приложения, который в нашем случае представляет собой строку «Без названия - FRM». Сообщение «String too long or IO Error» означает, что функция Dump не может вывести символы кириллицы. Попробуйте с помощью команды приложения ФайлèОткрыть открыть любой файл с именем, не содержащим символов кириллицы, и вы увидите имя этого файла в обсуждаемой строке.

Если Вы попробуете ввести фамилию символами кириллицы, Вы также в окне Debug увидите сообщение «m_strName = String too long or IO Error». В документе фамилия будет сохраняться корректно, но вот в окне отладки мы в лучшем случае увидим «крякозябры». Вывести символы кириллицы в окно отладки можно, например, так:

char Buf[300];char * GetANSI(CString str){ WideCharToMultiByte(1251,WC_NO_BEST_FIT_CHARS, str,-1,Buf,sizeof(Buf),0,0); return Buf;}TRACE(GetANSI(m_student.m_strName));

А вы не забыли разработать свой собственный класс и добавить на форму элементы, предназначенные для ввода его член-данных?


13. Разработка приложения с архитектурой «документ-вид». Часть 2

Программисты действуют рационально, лишь тогда, когда другие способы исчерпаны

Закон Мерфи

Цель работы – освоить использование списка объектов в приложении, основанном на архитектуре «документ-вид» (4 час.).

Приложение, которое должно быть разработано в этой второй части работы, отличается от приложения первой части следующими свойствами:

1. Вместо одного объекта класса CStudent документ должен содержать список таких объектов. (Теперь Вы понимаете, почему мы использовали класс CStudent вместо того, чтобы сделать m_strName и m_nGrade переменными-членами класса «документ».)

2. Кнопки на панели инструментов приложения должны позволять перемещаться по списку объектов CStudent.

3. Структура программы теперь должна допускать дополнительные представления данных. Команда Clear All теперь передается объекту «документ» и поэтому в игру вступают функции UpdateAllViews и OnUpdate для обновления его представления.

 

Сценарий этой работы, как и предыдущей, основан на материале глав 16 и 17 работы [1].

Задание.

1. Проработайте методические указания по работе со списками объектов.

2. Создайте приложение в соответствии с приведенным ниже сценарием.

3. Выполните отладку и добейтесь работоспособности приложения. Не забудьте о самостоятельной работе по доработке приложения (шаг 11).

4. Осмыслите полученный результат, примененный инструментарий и приемы программирования операций со списком объектов.

5. Сдайте работу.

 

Класс коллекций CObList

 

Познакомившись с классами коллекций, Вы удивитесь, как до сих пор без них обходились. Один из представителей этого семейства классов — CObList. Освоив его, Вы легко разберетесь в других классах списков (list classes), а также классах массивов (array classes) и классах ассоциативных массивов (map classes).

Может быть, Вам показалось, что коллекции – это что-то новое? Однако язык программирования С всегда поддерживал одну из их разновидностей – массивы. Однако, размер массивов в языке С фиксирован, они не поддерживают вставку новых элементов или удаление имеющихся, не контролируют выход индекса за границы массивов. Многие программисты на С писали библиотеки для других коллекций, включая связанные списки (linked lists), динамические массивы (dynamic array) и индексируемые словари (indexed dictionaries). В языке C++ есть очевидная и более удачная (по сравнению с библиотекой С-функций) альтернатива по реализации коллекций – это классы. Например, объект-список корректно инкапсулирует внутренние структуры данных списка.

Класс CObList поддерживает упорядоченные списки указателей на объекты классов, производных от CObject. Другой MFC-класс коллекций, CPtrList, вместо указателей на CObject хранит указатели void. Почему бы не использовать его вместо CObList? Класс CObList имеет ряд преимуществ при выводе диагностической информации, в чем Вы убедитесь далее, и при сериализации (serialization). Одно из важных свойств CObList — способность хранить смешанные указатели (mixed pointers). Другими словами, коллекция CObList может одновременно содержать указатели как на объекты CStudent, так и на объекты, например, CTeacher, если оба эти класса производны от CObject.

 

Применение класса CObList для создания списков типа FIFO

 

Одно из простейших примеров применений объекта CObList — добавление новых элементов в конец и выборка элементов из начала списка. Элемент, первым внесенный в список, будет первым и извлечен из него (принцип FIFO — First In, First Out, т. е. «первым вошел, первым вышел»). Допустим, элементы списка — объекты созданного Вами класса CAction, производного от CObject. Приведенная ниже консольная программа заносит в список пять элементов, а затем извлекает их в том же порядке.

#include <afx.h>#include <afxcoll.h> class CAction: public CObject{private: int m_nTime;public: CAction(int nTime) { m_nTime = nTime; } /* Конструктор запоминает время как целое число */ void PrintTime() { TRACE("time = %d\n", m_nTime); }}; int main(){ CAction* pAction; CObList actionList; // список создается в стеке int i; // вставляем в список actionList объекты CAction в порядке от 0 до 4 for (i = 0; i < 5; i++) { pAction = new CAction(i); actionList.AddTail(pAction); // приведение типа для pAction не требуется } // извлекаем и удаляем CAction в порядке от 0 до 4 while (!actionList.IsEmpty()) { pAction =(CAction*) actionList.RemoveHead();/* Для возвращаемого значения приведение типа необходимо */ pAction->PrintTime(); delete pAction; } return 0;}

 

Вот что происходит в этой программе. Сначала создается объект actionList класса CObList. Затем при помощи функции-члена CObList::AddTail() в конец списка добавляются указатели на вновь создаваемые объекты pAction. Преобразование типа для pAction не требуется, так как параметром служит указатель на CObject, a pAction – указатель на производный от него класс (вспомните правила совместимости классов одной иерархии). Далее указатели на объекты CAction извлекаются из начала списка с помощью функции-члена CObList::RemoveHead() и объекты уничтожаются. В данном случае для возвращаемого функцией RemoveHead() значения необходимо приведение типа, поскольку она возвращает указатель на класс, расположенный в иерархии классов выше класса CAction.

Когда Вы извлекаете указатель на объект из коллекции, сам объект автоматически не уничтожается. Удалять объекты CAction нужно с помощью операции delete, что и выполняется в программе.

 

Перебор элементов CObList – переменная типа POSITION

 

Предположим, Вам надо «пройти» все элементы списка. Класс CObList имеет функцию-член GetNext(), которая возвращает указатель на «следующий» элемент списка, но принцип ее использования необычен. GetNext() принимает целочисленный параметр типа POSITION *. Он содержит внутреннее представление положения извлекаемого элемента в списке. Так как параметр POSITION передается по ссылке (&), функция может изменить его значение.

Функция GetNext() выполняет следующие операции.

1. Возвращает указатель на «текущий» элемент списка, который определяется передаваемым ей значением POSITION.

2. Изменяет значение параметра POSITION так, чтобы он соответствовал положению следующего элемента списка.

Вот как выглядит цикл с GetNext(), если Вы используете список из предыдущего примера:

CAction* pAction;POSITION pos = actionList.GetHeadPosition();while (pos!= NULL) { pAction = (CAction*) actionList.GetNext(pos); pAction->PrintTime();}

 

Теперь допустим, что у Вас есть приложение, в котором для перемещения вперед и назад по элементам списка применяются кнопки панели инструментов. Для выбора очередного элемента функция GetNext() не годится, потому что она всегда увеличивает значение переменной POSITION, а предугадать, следующий или предыдущий элемент потребуется пользователю, просто невозможно. Взгляните на пример обработчика командного сообщения в классе «вид», который выбирает следующий элемент списка. Здесь m_actionList – объект типа CObList, внедренный в класс CMyView, а m_position – переменная типа POSITION, хранящая положение текущего элемента списка.

CMyView::OnCommandNext(){ POSITION pos; CAction* pAction; if ((pos = m_position)!= NULL) { m_actionList.GetNext(pos); if (pos!= NULL) // pos==NULL в конце списка { pAction = (CAction*) m_actionList.GetAt(pos); pAction->PrintTime(); m_position = pos; } else AfxMessageBox("Достигнут конец списка"); }}

 

Чтобы увеличить переменную положения – вызывают GetNext(), а чтобы получить элемент – используют функцию CObList::GetAt(). Переменная m_position обновляется, только если конец списка еще не достигнут.

 

Класс-шаблон коллекции CTypedPtrList

 

Класс CObList отлично работает, когда нужна коллекция, содержащая смешанные указатели. Однако если требуется набор с безопасным приведением типов, содержащий указатели только на один тип объектов, используйте классы-шаблоны коллекций указателей из MFC-библиотеки. Пример такого шаблонного класса — CTypedPtrList. Шаблоны (templates) – относительно новый элемент C++, впервые появившийся в Microsoft Visual C++ 2.0. CTypedPtrList — это класс-шаблон, который можно использовать для создания списка указателей на объекты любого заданного класса. Не вдаваясь в подробности, скажем только, что шаблон применяют для создания нового класса списка, производного либо от CPtrList, либо от CObList.

Объявить объект-коллекцию для указателей на CAction можно так:

CTypedPtrList <CObList, CAction *> m_actionList;

 

Первый параметр шаблона – это базовый класс для набора, второй — тип параметров и возвращаемых значений. В качестве базовых допускаются только классы CPtrList и CObList, так как других классов коллекций указателей в библиотеке MFC нет. Если Вы храните объекты классов, производных от CObject, используйте как базовый класс CObList; в ином случае — CPtrList.

При таком использовании шаблона, как показано выше, компилятор гарантирует, что все функции-члены списка возвращают указатель на CAction. Таким образом, можно писать:

pAction = m_actionList.GetAt(pos); // приведение типа не требуется

Чтобы слегка упростить описание объекта m_actionList, сгенерируем некое подобие самостоятельного класса с помощью описания типа typedef:

typedef CTypedPtrList <CObList, CAction *> CActionList;

 

и тогда m_actionList можно объявить так:

CActionList m_actionList;

 

Диагностика и классы наборов

 

Функция Dump для CObList и других классов наборов обладает одним весьма полезным свойством. Вызвав Dump для какого-либо объекта-коллекции, Вы получите информацию о каждом объекте из коллекции. Если в классах объектов, составляющих коллекцию, применены макросы DECLARE_DYNAMIC и IMPLEMENT_DYNAMIC, в информации появится имя класса каждого объекта.

По умолчанию функции Dump для коллекций выводят только имена классов и адреса объектов в коллекции. Чтобы функции Dump для коллекций вызывали функцию Dump для каждого элемента коллекции, где-то в начале программы надо сделать вызов:

#ifdef _DEBUG afxDump.SetDepth(1);#endif

Тогда оператор

#ifdef _DEBUG afxDump << actionList;#endif

 

будет выводить информацию примерно так:

a CObList at $411832with 4 elements a CAction at $412CD6time = 0 a CAction at $412632time = 1 a CAction at $41268Etime = 2 a CAction at $4126EAtime = 3

 

Если в наборе содержатся смешанные указатели, для класса объекта вызывается виртуальная функция Dump и выводится имя соответствующего класса.

 




Поделиться с друзьями:


Дата добавления: 2014-12-26; Просмотров: 423; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.12 сек.