Тема: Объявление и описание классов

Класс — это тип данных, определяемый пользователем. То, что в C++Builder имеется множество предопределенных классов, не противоречит этому определе­нию — ведь разработчики C++Builder тоже пользователи С++. Понятия класса, структуры и объединения в С++ довольно близки друг к другу.

Класс должен быть объявлен до того, как будет объявлена хотя бы одна перемен­ная этого класса. Т.е. класс не может объявляться внутри объявления переменной. Синтаксис объявления класса следующий:

class <имя класса> : <список классов - родителей>

{

public: // доступно всем

<данные, методы, свойства, события>

__published // видны в Инспекторе Объекта и изменяемы

<данные, свойства> protected: // доступно только потомкам

<данные, методы, свойства, события> private: // доступно только в классе

<данные, методы, свойства, события>

} <список переменных>;

Например:

class MyClass : public Classl, Class2

{

public:

MyClass(int = 0);

void SetA(int);

int GetA(void);

private: int FA;

double В, C;

protected:

int F(int);

};

Имя класса может быть любым допустимым идентификатором. Идентифика­торы классов, наследующих классам библиотеки компонентов C++Builder, приня­то начинать с символа «Т».

Класс может наследовать поля (они называются данные-элементы), методы (они называются функции-элементы), свойства, события от других классов — своих предков, может отменять какие-то из этих элементов класса или вводить новые. Если предусматриваются такие классы-предки, то в объявлении класса после его имени ставится двоеточие и затем дается список родителей. В приведенном выше примере предусмотрено множественное наследование классам Class1 и CIass2. Если среди классов-предков встречаются классы библиотеки компонентов C++Builder или классы, наследующие им, то множественное наследование запрещено.

Бели объявляемый класс не имеет предшественников, то список классов-роди­телей вместе с предшествующим двоеточием опускается. Например:

class MyClass1

{

};

Доступ к объявляемым элементам класса определяется тем, в каком разделе они объявлены. Раздел public (открытый) предназначен для объявлений, которые доступны для внешнего использования. Это открытый интерфейс класса. Раздел published (публикуемый) содержит открытые свойства, которые появляются в процессе проектирования на странице свойств Инспектора Объектов и которые, следовательно, пользователь может устанавливать в процессе проектирования. Раздел private (закрытый) содержит объявления полей и функций, используемых только внутри данного класса. Раздел protected (защищенный) содержит объявле­ния, доступные только для потомков объявляемого класса. Как и в случае закры­тых элементов, можно скрыть детали реализации защищенных элементов от ко­нечного пользователя. Однако в отличие от закрытых, защищенные элементы ос­таются доступны для программистов, которые захотят производить от этого класса производные классы, причем не требуется, чтобы производные классы объявля­лись в этом же модуле.

В приведенном выше примере черёз объект данного класса можно получить доступ только к функциям MyClass, SetA и GfetA. Поля FA, В, С и функция F — закрытые элементы. Это вспомогательные данные и функция, которые использу­ют в своей работе открытые функции. Открытая функция MyClass с именем, сов­падающим с именем класса, это так называемый конструктор класса, который должен инициализировать данные в момент создания объекта класса. Присутст­вие конструктора в объявлении класса не обязательно. При отсутствии конструк­тора пользователь должен сам позаботиться о задании начальных значений дан­ным-элементам класса.

Перед именами классов-родителей в объявлении класса также может указы­ваться спецификатор доступа (в примере public). Смысл этого спецификатора тот же, что и для элементов класса: при наследовании public (открытом наследовании) можно обращаться через объект данного класса к методам и свойствам клас­сов-предков, при наследовании private подобное обращение невозможно.

По умолчанию в классах (в отличие от структур) предполагается спецификатор private. Поэтому можно включать в объявление класса данные и функции, не ука­зывая спецификатора доступа. Все, что включено в описание до первого специфика­тора доступа, считается защищенным. Аналогично, если не указан спецификатор перед списком классов-родителей, предполагается защищенное наследование.

Объявления данных-элементов (полей) выглядят так же, как объявления пе­ременных или объявления полей в структурах:

<тип> <имена полой>;

В объявлении класса поля запрещается инициализировать. Для инициализа­ции данных служат конструкторы.

Объявления функций-элементов в простейшем случае не отличаются от обыч­ных объявлений функций.

После того, как объявлен класс, можно создавать объекты этого класса. Если ваш класс не наследует классам библиотеки компонентов C++Builder, то объект класса создается как любая переменная другого типа простым объявлением. На­пример, оператор:

MyClass МС, МС10[10], *Pmc;

создает объект МС объявленного выше класса MyClass, массив МС10 из десяти объектов данного класса и указатель Pmc на объект этого класса.

В момент создания объекта класса, имеющего конструктор, можно инициали­зировать его данные, перечисляя в скобках после имени объекта значения данных. Например, оператор:

MyClass МС(3);

не только создает объект МС, но и задает его полю FA значение 3, Если этого не сделать, то в момент создания объекта поле получит значение по умолчанию, ука­занное в содержащемся в объявлении класса прототипе конструктора.

Создание переменных, использующих класс, можно совместить с объявлени­ем самого класса, размещая их список между закрывающей класс фигурной скоб­кой и завершающей точкой с запятой. Например:

class MyClass : public Classl, Class2

{

} МС, MC10[10], *Pmc;

Если создается динамически размещаемый объект класса, то это делается операцией new. Например:

MyClass *РМС = new MyClass;

или

MyClass *РМС1 = new MyClass(3);

Эти операторы создают где-то в динамически распределяемой области памяти сами объекты и создают указатели на них — переменные РМС и РМС1.

Создание объектов класса простым объявлением переменных возможно толь­ко в случае, если среди предков вашего класса нет классов библиотеки компонен­тов С++Builder. Если же такие предки есть, то создание указателя на объект этого класса возможно только операцией new. Например, если класс объявлен так:

class MyClass2 : public TObject

{

};

то создание указателя на объект этого класса может осуществляться оператором:

MyClass2 *Р2 = new MyClass2;

Функции-элементы, дружественные функции, константные функции

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

Поэтому данные всегда целесообразно объявлять в разделе private — закрытом разделе класса. В редких случаях их можно помещать в protected — защищенном разделе класса, чтобы возможные потомки данного класса имели к ним доступ.

Как правило, делайте данные-элементы класса защищенными, снабжая их при необходимо­сти открытыми функциями чтения и записи. Функции записи позволят вам проверять записы­ваемые данные и обеспечивать тем самым непротиворечивость данных. А функции чтения позволят вам не переписывать программу, доже если вы решили изменить что-то в типе, способах хранения и размещения данных в классе,

Приведем пример. Пусть класс имеет следующее объявление:

Class MyClass

{

public:

void SetA(int); // функция записи

int GetA(void); // функция чтения

private: int FA;

double В, C;

};

Реализация функций записи и чтения может иметь вид:

void MyClass::SetA(int Value)

{

if(...) // проверка корректности данных

FA = Value;

}

int MyClass::GetA(void) {return FA;}

В данном случае функция чтения просто возвращает значение поля, но в более сложных классах может потребоваться какая-то предварительная обработка дан­ных. Обратите внимание, что все описания функций-элементов содержат ссылку на класс с помощью операции разрешения области действия (::).

В приведенном примере объявление класса содержит только прототипы функ­ций, а их реализация вынесена из описания класса. Для простых функций реали­зация может быть размещена непосредственно в объявлении класса. Например:

class MyClass

{

public:

MyClass(int = 0);

void SetA(int Value) {FA = Value;}; // функция записи

int GetA(void) {return FA;}; // функция чтения

private: int FA; double В, C;

};

Функции, описание которых содержится непосредственно в объявлении клас­са, в действительности являются встраиваемыми функциями inline.

Введение описания функций в объявление класса — это плохой стиль про­граммирования: следует избегать смешения открытого интерфейса класса, содер­жащегося в его объявлении, и реализации класса. Если уж вы хотите реализовать встраиваемые функции, то лучше поместить в объявлении класса их прототип со спецификатором inline:

inline void SetA{int}; // функция записи

и отдельно дать реализацию функции. При этом в реализации спецификатор inline не указывается.

Объявления классов следует размещать в заголовочном файле модуля, а реализацию функ­ций-элементов в отдельном файле реализации. При этом в объявлении класса должны содер­жаться только прототипы функций. Это следует из принципа скрытия информации — одного из основных в объектно-ориентированном программировании. Такая организация программы обеспечивает независимость всех модулей, использующих заголовочный файл с объявле­нием класса, от каких-то изменений в реализации функций-элементов класса.

Функции-элементы класса имеют доступ к любым другим функциям-элементам и к любым данным-элементам, как открытым, так и закрытым. Клиенты класса (какие-то внешние функции, работающие с объектами данного класса) име­ют доступ только к открытым функциям-элементам и данным-элементам. Но в не­которых случаях желательно обеспечить доступ к закрытым элементам для функ­ций, не являющихся элементами данного класса. Это можно сделать, объявив со­ответствующую функцию как друга класса с помощью спецификации friend. На­пример, если в объявление класса включить оператор:

friend void IncFA(MyClass *);

то функция IncFA, не являясь элементом данного класса, получает доступ к его за­крытым элементам. Например, функция IncFA может быть описана где-то в про­грамме следующим образом:

void IncFA(MyClass *Р) {P->FA++;}

Дружественными могут быть не только функции, но и целые классы. Напри­мер, вы можете поместить в объявление своего класса оператор:

friend Class1;

и все функции-элементы класса Class1 получат доступ к закрытым элементам ва­шего класса.

Иногда программист может захотеть создать объект вашего класса как кон­стантный с помощью спецификатора const. Например:

const Class1 MCI (3);

Если при этом ваш класс содержит не только функции чтения, но и записи дан­ных, то реакция на такой оператор, введенный пользователем, зависит от версии и настройки компилятора. Компилятор может выдать сообщение об ошибке и отка­заться от компиляции, а может просто выдать предупреждение и проигнорировать спецификатор пользователя const. Если же ваш класс содержит только функции чтения, то все должно бы быть нормально. Но компилятор подойдет к этому чисто формально и все равно выдаст предупреждение, а может и отказаться компилиро­вать программу.

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

int GetA(void) const;

а реализацию этой функции оформить как:

int MyClass::GetA(void) const {return FA;}

Тогда неприятные замечания компилятора о константных объектах исчезнут.

Если предполагается, что объект вашего класса может быть объявлен константным, снаб­жайте все функции-элементы класса, предназначенные для чтения данных, спецификаторами const.

Задания для лабораторной работы №6

Вариант 1. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме график экспоненциальной функции.

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

Вариант 3. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме график функции, описываемой квадратным уравнением.

Вариант 4. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме пирамиду из квадрата, круга и треугольника.

Вариант 5. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме вращающийся круг.

Вариант 6. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме вертикально расположенную цепочку из 5 колец.

Вариант 7. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме график функции

Вариант 8. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме движущийся круг.

Вариант 9. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме оси декартовой системы координат с нанесением на оси делений и оцифровки для заданного диапазонов изменения величин по оси х и оси у.

Вариант 10. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме вращающийся квадрат.

Вариант 11. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме круг, сектора которого раскрашены в различные цвета.

Вариант 12. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме летящий круг по заданной траектории.

Вариант 13. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме траекторию полета шара брошенного мод заданным углом с заданной начальной скоростью.

Вариант 14. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме график функции.

Вариант 15. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме изображение пирамиды в аксонометрической проекции.

Вариант 16. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме график функции.

Вариант 17. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме два разноцветных треугольника, стоящих вертикально, один на вершине другого вершиной вниз.

Вариант 18. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме ломанную линию в виде ступенек лестницы.

Вариант 19. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме пирамиду из стоящих друг на друге квадратов, уменьшающегося размера.

Вариант 20. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме лестницу из прямоугольников.

Вариант 21. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме прямоугольник, разделенный диагоналями на сектора, и закрасьте каждый сектор своим цветом.

Вариант 22. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме вращающийся квадрат.

Вариант 23. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме первый квадрант декартовой системы координат, с нанесенными делениями и оцифровкой осей.

Вариант 24. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме цепочку из разноцветных овалов (эллипсов).

Вариант 25. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме заполнение формы небольшими разноцветными кружочками (конфетти).

Вариант 26. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме прыгающий шарик.

Вариант 27. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме падающий квадрат.

Вариант 28. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме флаг Российской Федерации.

Вариант 29. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме пятиконечную звезду, окрашенную в красный цвет.

Вариант 30. Разработайте алгоритм, интерфейс пользователя и программу, позволяющую отобразить на форме шестиугольник, у которого каждый сектор окрашен в свой цвет.

Наши рекомендации