некоторые моменты анализа и структурного представления с++

advertisement
НЕКОТОРЫЕ МОМЕНТЫ АНАЛИЗА И СТРУКТУРНОГО
ПРЕДСТАВЛЕНИЯ С++ ПРОГРАММ
А.В. Яновский
Томский государственный университет систем управления
и радиоэлектроники, г. Томск
Статья «Некоторые моменты анализа и структурного представления С++
программ» посвящена проблемам изучения объектно-ориентированных языков программирования, таких как С++ и структурно-графическому их представлению.
SOME POINTS OF THE ANALYSIS AND STRUCTURAL
PRESENTATION C++ PROGRAMS
А.V. Janovskij
This article “Some points ot the analysis and structural presentation C++ programs” is about scientifical problems of study and structural presentation of programs creating on the C++ and other object programming languages.
Практика показывает, что изучение студентами объектно-ориентированных
языков программирования таких, как С++, например, сопряжено с рядом
трудностей. Овладение устойчивыми навыками программирования на С++
невозможно без овладения в той или иной степени языком программирования
Си. Язык Си является базисом, над которым надстраивался в свое время С++.
Но если студент, имеющий устойчивые стереотипы программирования на Си,
приступит к освоению С++, то он сталкнется с большой проблемой. Надо
помнить, что Си является языком функций, в то время как С++ является языком классов или, другими словами, объектов. Следовательно, концептуальный стержень программы, написанной на С++ будет существенно отличаться
от концептуального стержня программы, написанной на Си. Если Сипрограмма строится вокруг главной функции main(), то программа, написанная на С++ будет иметь совершенно отличное представление, основанное на
классах и ничего общего с концептуальной линией языка Си иметь не будет.
Помочь студенту разобраться, в новой для него объектно-ориентированной
парадигме призвано структурно-графическое представление С++ программ.
Структурно-графическое представление С++ программ реализуется с помощью разного рода анализаторов, помогающих представить графически структуру программы, и тем самым облегчить ее анализ.
При разработке программных продуктов с элементами анализа и графического представления кодов, написанных на С++, отправной точкой может
служить то, что С++ изначально замышлялся как язык объектно1
ориентированного программирования, сочетающий программную «мощь»
своего предшественника языка Си и достоинства объектно-ориентированного
подхода. Объектно-ориентированное программирование позволяет программисту объединять данные и обрабатывающий их программный код в один
блок. В С++ объекты реализуются с помощью классов, которые позволяют
программисту определять новые типы данных, так называемые пользовательские типы. Графически класс представляется в форме дерева (Рис. 1).
Рис. 1. Древовидное представление С++ класса, сгенерированное анализатором С++ программ
С++ позволяет создавать пользовательские типы данных не только внутри
других пользовательских типов, но и внутри функций, внутри операторов:
class a
{
struct b
{
union a{ } ;
};
};
main ( )
{
class a{ } ;
for( int a = 0 ; a < 10 ; a++ )
{
2
class a
{
int a;
};
}
}
Данная программа пройдет С++ компилятор и предел вложенности объектов наступит только тогда, когда во вложенный оператор for class a мы попытаемся поместить еще один пользовательский тип.
К понятию класса, пользовательского типа вплотную примыкает понятие
общего интерфейса [4]. Это подразумевает использование общей и частной
видимости членов класса, что дает возможность скрыть члены класса от
функций, не входящих в этот класс. В классе могут быть и общие, и частные
члены. Общие члены класса определяют то, как функции, не являющиеся
членами этого класса, могут использовать данный класс. Эти члены класса
называются общим интерфейсом класса.
Хорошо разработанный интерфейс обычно включает в себя функциичлены, которые выполняют следующее:
— Инициализируют переменную типа данного класса. Конструкторы всегда имеют тип public;
— Освобождают память, используемую переменной класса. Деструкторы
всегда имеют тип public;
— Производят первоначальную установку значений частных переменных — членов класса;
— Вычисляют значения частных переменных — членов класса;
— Выполняют реальную работу объекта.
Например:
class Shape
{
public:
Shape( float Aside, float Bside, float Cside );
~Shape( );
float volume( );
void SetA( float newA );
void SetB( float newB );
void SetC( float newC );
3
float GetA( );
float GetB( );
float GetC( );
private:
float a, b, c;
float square( );
};
В этом классе девять функций образуют общий интерфейс. Функции Shape
и ~Shape являются конструктором и деструктором класса.
Следующая функция — это volume выполняет реальную работу по вычислению объема прямоугольного параллелепипеда, ту работу, для которой данный класс и был разработан. И, наконец, шесть функций Get… и Set… позволяют функциям, не являющимся членами данного класса, управлять данными-членами класса (т.е. отыскивать и изменять значения частных переменных).
Описав общий интерфейс с этими функциями доступа к данным вместо
разрешения прямого доступа к данным-членам, программа класса может изменить способ хранения данных-членов, не влияя на программы, в которых
этот класс используется. Это и является основной целью скрытия данных и
надлежащего описания общего интерфейса класса.
Другой парадигмой объектно-ориентированного программирования, которую необходимо учитывать при анализе С++ программ, является наследование. Механизм наследования предоставляет возможность многократного использования объекта после корректировки его там, где необходимо. С++ дает
возможность описать базовые классы (родители) и производные классы (потомки). Производные классы наследуют все общие данные члены и общие
функции члены базового класса. Это делает их частью общего интерфейса.
Важным моментом при анализе и дальнейшем графическом представлении
С++ программы является то, что производный класс в состоянии породить
следующий производный класс (Рис. 2).
Базовый класс
Производный
класс
Производный
класс
Производный
класс
Производный
класс
4
Рис. 2. Иерархия классов в С++
При создании разного рода анализаторов С++ программ, призванных облегчить обучение объектно-ориентированным языкам программирования,
помимо учета основных парадигм объектно-ориентированного программирования — классов, их видимости, наследования [5] при анализе C++ программ
необходимо четко представлять структуру самой программы [3].
Практически любая программа, написанная на C++, начинается с подключения заголовочных файлов посредством включающей директивы препроцессора include [4]. Эти файлы с расширением .h содержат тексты на языке C++.
Внутри заголовочного файла может содержаться вызов другого файла с расширением .h и т. д. (рис. 3)
Заголовочный
файл
Заголовочный
файл
Заголовочный
файл
Рис. 3. Структура последовательных вызовов заголовочных файлов в C++.
В отличие от языка программирования Паскаль [2], например, в C++ отсутствует понятие процедуры. Все подпрограммы являются функциями во главе
с основной функцией main. Без main C++ программа не пройдет компилятор.
Напротив, в Паскале наличие главной функции необязательно. Минимальная
программа на Паскале выглядит begin end., в то время как аналогичная программа на C++ имеет вид: main(){}. В отличие от Паскаля (рис. 4) С++ не
предусматривает наличие одной подпрограммы внутри другой. Иерархия
подпрограмм (функций) строго определена – они следуют строго друг за другом (рис. 5).
Program test;
Var i, k: Integer;
Procedure Proc;
Function F1: Real;
Begin End;
Function F2: Real;
Begin End;
Begin End;
5
Function One: Real;
Begin End;
Function Two: Real;
Begin End;
Procedure Proc2;
Function Fun1: Real;
Begin End;
Function Fun2: Real;
Begin End;
Begin End;
Begin End;
Рис. 4. Структура подпрограмм, заданных на языке Паскаль, и отображающее ее
дерево процедур и функций.
6
Рис. 5. Дерево функций в языке программирования C++.
Вместе с тем, как и в языке программирования Паскаль, управляющие операторы C++ могут содержать один или более других управляющих операторов (рис. 6).
Рис. 6. Дерево операторов в C++.
7
Поэтому структура программы представляет собой дерево функций, к каждой ветви которого привязано дерево структурных операторов соответсвующей функции. Но и здесь есть нюанс. C++ предполагает самое широкое использование локальных переменных. Их можно задавать даже в операторе
цикла for:
for( int i = 0 ; i < n ; i++ );
При структурно-графическом отображении текста C++ программы возникает необходимость создания «разорванного» дерева данных, то есть дерева
данных, фрагменты которого будут располагаться не только внутри классов и
функций, но и внутри операторов.
Литература
1. Керниган Б., Ритчи Д. Язык программирования Си. — М.: ФИС,
1992. — 204 с.
2. Коффман Э. Б. Турбо Паскаль. — М.: Вильямс, 2002. — 892 с.
3. Погребной В. К., Демин А. Ю., Погребной Д. В. Томография и структурно-графическое представление программ. Сб. Математическое и
программное обеспечение САПР, вып. 1. — Томск: Изд. ТПУ, 1997. —
с. 8–16.
4. Поттс С., Монк Т. С. Borland C++ в примерах. — Минск: Попурри,
1996. — 723 с.
5. Яновский А. В. Особенности анализа и структурно–графического представления С++ программ // Вестник Московского городского педагогического университета. Серия «Информатика и информатизация образования». — М.: МГПУ, 2005. — 2(5). — с. 139–142.
8
Download