Простые типы 7 страница

INCLUDED.)
«define AFX_MAINFRM_H__AF072C87_900A_11DO_8860_444553540000__INCLUDED_

Bit _MSC_VER >= 1000
#pragma once
tfendif // _MSC_VER >= 1000
class CMainFrame: public CFrameWnd
{
protected: // создание только при сериализации
CMainFrameO;
DECLARE_DYNCREATE(CMainFrame)

// Атрибуты
public:
// Операции
public:
// Переопределения
// Переопределения виртуальных функций, сгенерированные ClassWizard
//({AFХ VIRTUAL(CMainFrame)
Virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Реализация
public:
virtual "CmainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // Внутренние управляющие объекты
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;

// Сгенерированные функции схемы сообщений
protected:
//{{AFX_MSG(CMainFrame)
afxjnsg int OnCreate(LPCREATESTRUCT IpCreateStruct);
// ВНИМАНИЕ - здесь ClassWizard вставляет и удаляет функции класса.
// НЕ ИЗМЕНЯЙТЕ содержимое этих частей сгенерированного кода!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ вставляет дополнительные объявления
// перед предшествующей строкой.

#endif
//
!defined(AFX_MAINFRM_H__8A1BC189_B34B_11D1_887F_D42B07C10710__INCLUDED_)
// MainFrm. cpp: реализация класса CMainFrame
//
#include "stdafx.h"
#include "welcome, h"
#include "MainFrm.h"
#ifdef _DEBUG

#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////У////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame. CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame. CFrameWnd)

//{{AFX_MSG_MAP(CMainFrame)
// ВНИМАНИЕ - здесь ClassWizard добавляет и удаляет макросы схемы.
// НЕ ИЗМЕНЯЙТЕ содержимое этих частей сгенерированного кода!
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static DINT indicators[] =
{
ID_SEPARATOR, // индикаторы строки состояния
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
/////////////////////////////////////////////////////////////////////////•
// Создание/уничтожение CMainFrame
CMainFrame::CMainFrame()

{
// TODO: добавьте код для инициализации переменных класса
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT IpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER |
CBRS_TOOLT1PS | CBRS_FLYBY |
CBRS|SIZE_DYNAMIC) | |
! m_wndToolBar. LoadToolBaг(IDR_MAINFRAME))
{
TRACEO ("Failed to create toolbar\n");
return -1; // неудачная попытка создания

}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.Setlndicatorstindicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACEO("Failed to create status bar\n");
return -1; // неудачная попытка создания
}
// TODO: Удалите следующие три строки, если вам не нужна
// закрепляемая панель инструментов
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableOocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

// TODO: Измените класс окна или его стили, редактируя
// содержимое CREATESTRUCT cs
return CFrameWnd::PreCreateWindow(cs);
/////////////////////////////////////////////////////////////////////
Диагностика в CMainFrame
#ifdef _DEBUG
void CMainFrame::AssertValid() const{
CFrameWnd::AssertValid();}
void CMainFrame::Dump(CDumpContext& dc) const
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
///////////////////////////////////////////////////////////////////////
// Обработчики сообщений CMainFrame

Перейдем к объекту вида — он отвечает за отображение данных из документа в
клиентской области окна программы. Большая часть наших действий связана
именно с объектом вида.

9.10.5. Исследуем объект вида
В объекте вида выводится наше сообщение «Добро пожаловать в Visual C++!».
Это происходит в методе OnDraw() файла welcomeView.cpp:
void CWelcomeView::OnDraw(CDС pDC)
{
CString welcome_string = "Добро пожаловать в Visual C++";
CWelcomeOoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

pDC->TextOut(0, 0, welcome_string);
}

Этот метод вызывается в ситуации, когда требуется перерисовать клиентскую об-
ласть. На самом деле именно так станут работать все наши программы — они бу-
дут разбиты на множество различных методов, предназначенных для обработки
конкретных сообщений Windows.

9.10.6. Программирование, управляемое событиями

Программы для Windows управляются событиями (event-driven). Это означает,
что они реагируют на действия пользователя, называемые событиями, — щелчки
кнопкой мыши, нажатия клавиш и т. д. При наступлении любого из этих событий
в программе вызывается соответствующий метод. Тем самым удается разбить ее
на небольшие методы, соответствующие различным сообщениям Windows. Напри-
мер, метод OnDraw() вызывается при необходимости перерисовать клиентскую
область — когда окно впервые отображается на экране, когда пользователь пере-
мещает окно, закрывавшее часть нашего окна, или же сворачивает и разворачива-
ет текущее окно.

Вывод сообщения в объекте вида
Что же происходит в методе OnDraw() при выводе текста? Прежде всего мы созда-
ем новый объект welcome_string, принадлежащий классу MFC CString, и заносим
в него текст:
void CwelcomeView::OnDraw(CDC* pDC)
{
CString welcome_string = "Добро пожаловать в Visual C++";
CWelcomeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(0, 0, welcome_string);
}
Класс CString содержит все операции со строками. Он чрезвычайно полезен и яв-
ляется заметным достижением по сравнению с принятой в языке С интерпрета-
цией строк как символьных массивов.
Класс CString содержит следующие методы:
AllocSysString AnsiToOem Collate
Compare CompareNoCase CString
Empty Find FindOneOf
Format FormatMessage FreeExtra
GetAt GetBuffer GetBufferSetLength
GetLength IsEmpty Left
LoadString LockBuffer MakeLower
MakeReverse MakeUpper Mid
OemToAnsi оператор [] оператор +
оператор += оператор «оператор =
оператор == < и т. д. оператор» оператор LPCTSTR
ReleaseBuffer ReverseFind Right
SetAt SetSysString SpanExcluding
Spanlncluding TnmLeft TrimRight
UnlockBuffer Методы, специфические
для Windows
Затем в методе OnDraw() мы выводим текстовую строку через переданный методу
указатель pDC, который ссылается на объект класса MFC с именем СDС. Конкрет-
но, мы вызываем метод TextOut() этого объекта:
void CWelcomeView::OnDraw(CDC* pDC)
{
CString welcome_string = "Добро пожаловать в Visual C++";
CWelcomeDoc* pOoc = GetDocumentO;
ASSERT_VALID(pDoc):
pDC->TextOut(0, 0, welcome_stnng);
}
Класс CDC чрезвычайно важен для нас, поскольку он предназначен для работы с контекстами устройств. Весь графический и текстовый вывод, выполняемый нами
I) Visual C++, будет осуществляться через контексты устройств.

Что такое контекст устройства?
Вы должны хорошо понимать, что такое «контекст устройства». Вообще говоря,
так называется область памяти, используемая в системе Windows для выполнения
графических операций. Графический вывод может выполняться как на экран, так
и на принтер. Объекты класса CDC содержат множество встроенных методов, используемых в процессе рисования в контексте устройства. Все рисование в Windows выполняется через контекст устройства.
Чтобы рисовать в нашем объекте вида, мы получаем контекст устройства, относя-
щийся к нему. Кроме того, можно получить контекст устройства для всего окна,
всего экрана или принтера. Для рисования в контексте устройства используются
перечисленные ниже методы класса CDC; обратите внимание на их количество.
AbortDoc AbortPath AddMetaFileComment
AngleArc Arc ArcTo
Attach BeginPath BitBlt
CDC Chord CloseFigure
CreateCompatibleDC CreateDC CreateIC
DeleteDC DeleteTempMap Detach
DPtoHIMETRIC DPtoLP DrawSdRect
DrawDragRect DrawEdge DrawEscape
DrawFocusRect DrawFrameControl Drawlcon
DrawState DrawText Ellipse
I ndOoc EndPage Endpath
InumObjects Escape ExcludeCllpRect

ExcludellpdateRgn ExtFloodFill ExtTextOut
FillPath FillRect FillRgn.
FillSolidRect FlattenPath FloodFlll

FrameRect FrameRgn FromHandle
GetArcDirection GetAspectRatioFilter GetBkColor
GetBkMode GetBoundsRect GetBrushOrg
GetCharABCWidths GetCharWidth GetClipBox
GetColorAdjustment GetCurrentBitmap GetCurrentBrush
GetCurrentFont GetCurrentPalette GetCurrentPen
GetCurrentPosition GetDeviceCaps GetFontData
GetGlyphOutline GetHalftoneBrush GetKerningPairs
GetMapMode GetMiterLimit GetNearestColor

GetOutlineTextMetrics GetOutputCharWidth GetOutputTabbedTextExtent

GetOutputTextExtent GetOutputTextMetrics GetPath
GetPixel GetPolyFillMode GetROP2
GetSafeHdc GetStretchBltMode GetTabbedTextExtent

GetTextAlign GetTextCharacterExtra GetTextColor

GetTextExtent GetTextFace GetTextMetrics
GetViewportExt GetViewportOrg GetWindow
GetWindowExt GetWindowOrg GrayString
HIMETRICtoDP HIMETRICtoLP IntersectClipRect
InvertRect InvertRgn LineTo
LPtoDP LPtoHIMETRIC MaskBlt
MoveTo OffsetClipRgn OffsetViewpotOrg
OffsetWindowOrg PaintRgn PatBlt
Pie PlayMetafile PlgBlt
PolyBezier PolyBezierTo PolyDraw
Polygon Polyline PolylineTo

PolyPolygon PolyPolyline PtVisible
QueryAbort ReallzePalette Rectangle
RectVisible ReleaseAttrlbDC ReleaseOutputDC
ResetDC RestoreDC RoundRect
SaveDC ScaleViewportExt ScaleWindowExt
ScrollDC SelectClipPath SelectClipRgn
SelectObject SelectPalette SelectStockObject
SetAbortProc SetArcDirection SetAttrlbDC
SetBkColor SetBkMode SetBoundsRect
SetBrushOrg SetColorAdjustment SetMapMode

SolMapperFlags SetMiterLimit SetOutputDC

SetPixel SetPixclV SetPolyFillMode
SetROP2 SetStretchBltMode SetTextAlign

SetTextCharacterExtra SetTextColor SetTextJustification

SotViewportExt SetViewportOrg SetWindowExt
SotWindowOrg StartDoc StartPage
MretchBlt StrokeAndFillPath StrokePath
labbedTextOut TextOut UpdateColors
WidenPath
Внашем случае для вывода в объекте вида (соответствующего клиентской облас-
ти окна) был использован метод TextOut класса CDC. Методу OnDraw() передается
указатель рDС, ссылающийся на контекст устройства для нашего вида. Чтобы вы-
нести текст welcome_string в клиентской области, достаточно выполнить следую-
щую строку:
pDC->TextOut(0, 0, welcome_string);
Методу TextOut () передаются координаты левого верхнего угла той области окна,
где должна располагаться наша строка. В нашем случае текст выводится с точки
(О, 0) — левого верхнего угла клиентской области. Затем метод получает саму стро-
ку, welcome_string.
Итак, выполнение этой строки программы приводит к тому, что наша строка вы-
водится на экран. Так данные программы отображаются в объекте вида.
В последующих уроках мы узнаем об объекте вида намного больше, потому что
именно с ним будет связана основная часть программирования. Исходный текст
объекта вида находится в файлах welcomeView.h/welcomeView.cpp.
welcomeView.h и welcomeView.cpp
// welcomeView. h: интерфейс класса CWelcomeView
//

////////////////////////////////////////////////////////////////////////
#if!defined(AFXjAlELCOMEVIEW_H__AF072C8B_900A_11DO_8860_444553540000__
INCLUDEDJ
#define AFX_WELCOMEVIEW_H__AF072C8B_900A_11DO_8860_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CWelcomeView: public CView
{
protected: // создание только при сериализации
CWelcomeViewO;
DECLARE_DYNCREATE(CWelcomeView)
// Атрибуты
public:
CWelcomeDoc* GetDocumentO;

// Операции
public:
// Переопределения
// Переопределения виртуальных функций, сгенерированные ClassWizard
//{{AFX_VIRTUAL(CWelcomeView)
public:
virtual void OnDraw(CDC* pDC); // переопределяется для рисования
// в текущем виде
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* plnfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintlnfo* plnfo);
virtual void OnEndPrinting(CDO pDC, CPrintlnfo* plnfo);
//}}AFX_VIRTUAL
// Реализация
public:
virtual "CWelcomeViewO;
#ifdef _DEBUG
virtual void AssertValidQ const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Сгенерированные функции схемы сообщений
protected:
//{{AFX_MSG(CWelcomeView)
// ВНИМАНИЕ - здесь ClassWizard вставляет и удаляет функции класса.
// НЕ ИЗМЕНЯЙТЕ содержимое этих блоков сгенерированного кода!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG // отладочная версия - в welcomeView.cpp
inline CWelcomeDoc* CWelcomeView::GetDocument()
{ return (CWelcomeDoc*)m_pDocument; }
#endif
////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ вставляет дополнительные объявления
// перед предшествующей строкой.
#endif
//!defined(AFX_WELCOMEVIEW_H__AF072C8B_900A_
// 11DO_8860_444553540000__INCLUDED_)
// welcomeView.cpp: реализация класса CWelcomeView
//
#include "stdafx.h"
#include "welcome.h"
#include "welcomeDoc. h"
#include "welcomeView. h"
#ifdef _DEBUG
tfdefine new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////
// CWelcomeView
IMPLEMENT_DYNCREATE(CWelcomeView, CView)
BEGIN_MESSAGE_MAP(CWelcomeView, CView)
//{{AFX_MSG_MAP(CWelcomeView)
// ВНИМАНИЕ - здесь ClassWizard добавляет и удаляет макросы схемы.
// НЕ ИЗМЕНЯЙТЕ содержимое этих частей сгенерированного кода!
//}}AFX_MSG_MAP
// Стандартные команды печати
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePnntPreview)
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////
// Создание/уничтожение CWelcomeView
CWelcomeView::CWelcomeView()
{
// TODO: добавьте код конструктора
}
CWelcomeView::"CWelcomeView()
{
}
BOOL CWelcomeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Измените класс окна или его стили, редактируя
// содержимое CREATESTRUCT cs
return CView::PreCreateWindow(cs);

}


II Рисование в CWelcomeView
void CWelcomeView::OnDraw(CDC* pDC)
{
CString welcome_string = "Добро пожаловать в Visual C++";
CWelcomeDoc* pDoc = GetDocumentO;
ASSERT_VALID(pDoc);
pDC->TextOut(0, 0, welcome_string.);
// T0DO: добавьте код для отображений данных
}
//////////////////////////////////////////У//////////////////////////////
// Печать в CWelcomeView
BOOL CWelcomeView::OnPreparePrinting(CPrintInfo* plnfo)
{
// Стандартная подготовка
return DoPreparePrinting(pInfo);
}
void CWelcomeView::OnBeginPrinting(CDC* /*pDO/, CPrintlnfo* /*plnfo*/)
{
// TODO: добавьте дополнительную инициализацию перед печатью
}
void CWelcomeView::OnEndPrinting(CDO /*pDO/, CPrintlnfo* /*plnfo*/)
{
// TODO: добавьте код для "сборки мусора" после печати
}
I/ Диагностика в CWelcomeView
#ifdef _DEBUG
void CWelcomeView::AssertValid() const
{
CView::AssertValid();
}
void CWelcomeView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CWelcomeDoc* CWelcomeView::GetDocument() // не-отладочная версия
// является встроенной
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWelcomeDoc)));
return (CWelcomeDoc*)m_pDocument;
}
#endif //_DEBUG
////////У////////////////////////////////////////////////////////////////
// Обработчики сообщений CWelcomeView
Объект вида отображает данные программы, которые обычно хранятся в объекте документа. Сейчас мы рассмотрим последний из четырех основных объектов нашей программы.

9.10.7.Исследуем объект документа
В объекте документа хранятся данные программы. В примере welcome нам потребовался только объект welcome_string. Для простоты мы разместили его в объекте вида, но на самом деле ему следовало бы находиться в объекте документа.
Как разместить welcome_string в объекте документа? Прежде всего нам следовало |
бы объявить welcome_string в заголовочном файле документа welcomeDoc.h:
// welcomeDoc.h: интерфейс класса CWelcomeDoc
////////////////////////////////////////////////////////////////////////i

#if!defined(AFX_WELCOMEDOC_H__AF072C89_900A_11DO_8860_444553540000__

INCLUDED.)
#define AFXJIELCOMEDOC_H_J\F072C89_900A_11DO_8860_444553540000__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CWelcomeDoc: public CDocument
{
protected: // создание только при сериализации
CWelcomeDocO;

DECLAREJ)YNCREATE(CWelcomeDoc)
••> CString welcome_Strlng;


1}
Затем мы инициализируем объект welcome_string в конструкторе класса докумен-
та, расположенном в файле welcomeDoc.cpp:
CWelcomeDoc::CWelcomeDocO
{

welcome_string = "Добро пожаловать в Visual C++!"
}
Данные хранятся в объекте документа и готовы к работе — но как обратиться к ним
из объекта вида?

9.10.8. Обращение к документу из вида
Если взглянуть на код, сгенерированный АррWizard для нашего класса вида, можно заметить, что в нем уже есть фрагмент для получения указателя на объект документа с помощью метода GetDocument() класса вида. Арр Wizard присвоил этому показателю имя pDoc:
void CWelcomeView::OnDraw(CDC* pDC)
{

CWelcomeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);}
()бращение к welcome_st ring в объекте документа может выглядеть так: pDoc->welcome_I t ring;, поэтому в итоге содержимое welcome_string будет отображаться следующим образом:

void CWelcomeView::OnDraw(CDC* pDC)

{

CWelcomeDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDC->TextOut(0, 0, pDoc->welcome_string);

}
Измененная программа будет работать как положено и выводить наше сообще-
ние. Разумеется, при таком маленьком объеме данных вряд ли стоит перемещать
их из объекта вида в объект документа. Обычно для хранения данных в послед-
нем находится одна, причем довольно веская причина — возможность записать
их на диске и затем прочесть. Давайте посмотрим, как это делается.

9.10.9. Сохранение данных на диске
Сохранение и загрузка данных будут подробно рассмотрены позднее, когда мы будем
заниматься работой с файлами, но один из аспектов этих операций можно изучить
прямо сейчас. В исходном файле документа, welcomeDoc.cpp, присутствует метод
Serialize():
void CWelcomeDoc::Serialize(CArchive& ar)
<
if (ar.IsStoring())
{

// TODO: добавьте код сохранения данных
}

else
{
// TODO: добавьте код загрузки данных
,
В нашей программе уже есть несколько встроенных команд меню для работы с файлами: Save, Save As и Open. Программа берет на себя почти всю работу по сохранению файла на диске, но мы должны изменить ее текст так, чтобы она сохраняла наш объект welcome_string.
Методу Serialize() передается объект с именем аr; с ним можно работать точно
так же, как и с потоком cout в предыдущем уроке. В частности, для сохранения
объекта welcome_string при записи данных на диск и для его последующего чтения при загрузке данных с диска следует добавить следующий фрагмент:
void CWelcomeDoc::Serialize(CArchive& ar)
{
if (ar.IsStoringO)

{
ar «welcome_string;

>

else

{
ar» welcome_string;
Теперь пользователь сможет сохранить документ на диске и загрузить его оттуда.,
Позднее мы рассмотрим эту тему более подробно, а для начала хватит и этого. Исходный текст объекта документа находится в файлах welcomeDoc.h и welcomeDoc.cpp.
welcomeDoc.h и welcomeDoc.cpp
// welcomeDoc.h: интерфейс класса CWelcomeDoc
//
/////////////////////////////////////////////////////////////////////////
#if!defined(AFX_WELCOMEDOC_H__AF072C89_900AJ1DO_8860_444553540000__
INCLUDED_)
#define AFX_WELCOMEDOC_H__AF072C89_900A_1DO_8860_444553540000__INCLUDED_
# if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CWelcomeDoc: public CDocument
{
protected: // создание только при сериализации
CwelcomeDoc();
DECLARE_DYNCREATE(CWelcomeDoc)
// Атрибуты
public:
// Операции
public:
// Переопределения
// Переопределения виртуальных функций, сгенерированные ClassWizard
//{{AFX_VIRTUAL(CWelcomeDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
//}}AFX_VIRTUAL
// Реализация
public:
virtual ~CWelcomeDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Сгенерированные функции схемы сообщений
protected:
//{{AFX_MSG(CWelcomeDoc)
// ВНИМАНИЕ - здесь ClassWizard вставляет и удаляет функции класса.
/ НЕ ИЗМЕНЯЙТЕ содержимое этих частей сгенерированного кода!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
},
///////////////////////////////////////////////////////////////////////У/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ вставляет дополнительные объявления
// перед предшествующей строкой.
#endif
// idefined(AFX_WELCOMEDOC_H__AF072C89_900A_
// 11DO_8860_444553540000__INCLUDED_)
// welcomeDoc cpp: реализация класса CWelcomeDoc
//
#include "stdafx.h'
#include "welcome.h"
#include "welcomeDoc.h",
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////
// CWelcomeDoc
IMPLEMENT_DYNCREATE(CWelcomeDoc, CDocument)
BEGIN_MESSAGE_MAP(CWelcomeDoc, CDocument)
//{{AFX_MSG_HAP'(CWelcomeDoc)
// ВНИМАНИЕ - здесь ClassWizara добавляет и удаляет макросы схемы.
// НЕ ИЗМЕНЯЙТЕ содержимое этих частей сгенерированного кода!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////
// Создание/уничтоение CWelcomeDoc

CWelcomeDoc::CWelcomeDoc()
{
// TODO: добавьте код конструктора
}
CWelcomeDoc::~CWelcomeDoc()
{
}
BOOL CWelcomeDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: добавьте код для повторной инициализации документа
// (документы SDI будут использовать его повторно)
return TRUE:
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Сериализация в CWelcomeDoc
void CWelcomeDoc::Senalize(CArchive& ar)
{
if (ar. IsStoring())
{
// TODO: добавьте код сохранения данных
}
else
{
// TODO: добавьте код загрузки данных
}
}
/////////////////////////////////////////////////////////////////////////
// Диагностика в CWelcomeDoc
#ifdef _DEBUG
void CWelcomeDoc::AssertValid() const
{
CDocument::AssertValid():
}
void CWelcomeDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //.DEBUG
/////////////////////////////////////////////////////////////////////////
// Команды CWelcomeDoc

9.10.10. Декомпозиция программ
И начинающие программисты, и руководители проектов, экстраполируя ту простоту и легкость, с какой один человек может написать отдельную программу, часто полагают, что разработать программную систему также просто. Нужно только подобрать группу программистов и поручить им работу. Однако существует глубокая пропасть между написанием (небольших) про-
грамм и созданием (больших) программных систем, и многие системы по-
ставляются с опозданием, с большим количеством ошибок и обходятся в несколько раз дороже, чем по первоначальной оценке.
Разработка программного обеспечения (software engineering) имеет дело с методами организации и управления группами разработчиков, с системой обозначений и инструментальными средствами, которые поддерживают этапы процесса разработки помимо программирования. Они включают этапы технического задания, проектирования и тестирования программного обеспечения.
В этой и двух последующих главах мы изучим конструкции языков программирования, которые разработаны для того, чтобы поддерживать создание больших программных систем. Не вызывает сомнений компромисс: чем меньшую поддержку предлагает язык для разработки больших систем, тем больше потребность в методах, соглашениях и системах обозначений, которые являются внешними по отношению к самому языку. Так как язык прграммирования, несомненно, необходим, кажется разумным включить поддержку больших систем в состав самого языка и ожидать, что компилятор по возможности автоматизирует максимальную часть процесса разработки. Мы,разработчики программного обеспечения, всегда хотим автоматизировать
чью-нибудь чужую работу, но часто приходим в состояние неуверенности перед тем, как включить автоматизацию в языки программирования.
Главная проблема состоит в том, как разложить большую программную систему на легко управляемые компоненты, которые можно разработать отдельно и собрать в систему, где все компоненты взаимодействовали бы друг с другом, как запланировано. Начнем обсуждение с элементарных "механических методов" декомпозиции программы и перейдем к таким современным
понятиям, как абстрактные типы данных и объектно-ориентированное программирование, которые направляют проектировщика системы на создание семантически значимых компонентов.
Перед тем как начать обсуждение, сделаем замечание для читателей, которые только начинают изучать программирование. Понятия будут продемонстрированы на небольших примерах, которые может вместить учебник, и вам может показаться, что это всего лишь излишняя «бюрократия». Будьте уверены, что поколениями программистов был пройден тяжелый путь, доказывающий, что такая бюрократия необходима; разница только в одном, либо она определена и реализована внутри стандарта языка, либо изобретается и внедряется администрацией для каждого нового проекта.

9.10.11. Раздельная компиляция
Первоначально декомпозиция программ делалась исключительно для того,чтобы дать возможность программисту раздельно компилировать компоненты программы. Благодаря мощности современных компьютеров и эффективности компиляторов эта причина теперь не столь существенна, как раньше, но важно изучить раздельную компиляцию, потому что для ее поддержки часто используются те же самые возможности, что и для декомпозиции программы на логические компоненты. Даже в очень больших системах, которые нельзя создать без раздельной компиляции, декомпозиция на компоненты делается при проектировании программы и не имеет отношения к этапу компиляции. Поскольку программные компоненты обычно относительно невелики, лимитирующим фактором при внесении изменений в программы обычно оказывается время компоновки, а не компиляции.

Раздельная компиляция в языке Fortran
Когда был разработан Fortran, программы вводились в компьютер с помощью
перфокарт, и не было никаких дисков или библиотек программ, которые известны сегодня.
Компилируемый модуль в языке Fortran идентичен выполняемому модулю, а именно подпрограмме, называемой сабрутиной (subroutine).Каждая сабрутина компилируется не только раздельно, но и независимо, и в результате одной компиляции не сохраняется никакой информации, которую можно использовать при последующих компиляциях.
Это означает, что не делается абсолютно никакой проверки на соответствие формальных и фактических параметров. Вы можете задать значение с плававающей точкой для целочисленного параметра. Более того, массив передаётся как указатель на первый элемент, и вызванная подпрограмма никак не может узнать размер массива или даже тип элементов. Подпрограмма может даже попытаться обратиться к несуществующему фактическому параметру.
Другими словами, согласование формальных и фактических параметров задача программиста; именно он должен обеспечить правильные объявления типов и размеров параметров, как в вызывающих, так и вызываемых подпро-
граммах. Поскольку каждая подпрограмма компилируется независимо, нельзя со-
вместно использовать глобальные объявления данных. Вместо этого опреде-
лены общие (common) блоки:

subroutine S1
common /block1/ distance(100), speed(100), time(100)
real distance, speed, time
end
Это объявление требует выделить 300 ячеек памяти для значений с плаваю-
щей точкой. Все другие объявления для этого же блока распределяются в те же
самые ячейки памяти, поэтому, если другая подпрограмма объявляет:
subroutine S2
common /block/ speed(200), time(200), distance(200)
integer speed, time, distance


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: