logo
Объектно-ориентированное программирование и C++

Variant Вариантное значение, 16 байт Variant class

TdateTime Значение даты и времени, 64-битовое плавающее число TDateTime class

Currency Валюта, 64-битовое плавающее число, 4 цифры после точки Currency class

Set (множество) служит для спецификации типа параметров объектных методов VCL или типа значений, возвращаемых этими методами. C++Builder реализует этот встроенный тип Delphi с помощью одноименного шаблонного класса Set<type, minval, maxval> со следующими параметрами:

type тип элементов множества (обычно, int. char или enum):

minval минимальное (положительное) значение, которое могут принимать элементы множества;

maxval максимальное (не более 255) значение, которое могут принимать элементы множества.

Подстановка разных значений параметров приводит к созданию экземпляров шаблонного класса Set различных типов, поэтому оператор сравнения if (si == s 2) объектов, описанных как

Set<char, 'A', 'C'> si;

Set<char, 'X', 'Z'> s2;

вызовет ошибку компиляции. Для создания множественных экземпляров типа Set необходимо использовать ключевое слово typedef. Например, объявив typedef Set<char, 'A','Z'> UpperCaseSet; можно создать множества UpperCaseSet si; и UpperCaseSet s2; а затем инициализировать эти объекты:

s1 “ 'А' “ 'В' “ 'С' ;

s2 “ 'X' “ 'Y' “ '?.' ;

AnsiString используется для спецификации типа текстовых строк произвольной длины, имеющих следующую характерную внутреннюю структуру:

счетчик

длина строки

данные

терминатор \0

C++Builder реализует этот встроенный тип Delphi как одноименный класс. Если при создании экземпляров данного класса не указано начальное значение строки, конструктор AnsiString автоматически присваивает всем переменным нулевые значения. Среди методов данного класса отметим наиболее часто вызываемый метод с str (), который возвращает указатель на символьный массив, оканчивающийся 0 и содержащий копию символов, заключенных в исходном объекте типа AnsiString. Листинг 3.18 иллюстрирует "применение методов чтения и записи значения члена данных FNames свойства Names типа AnsiString в экземпляре MyFamily объявленного компонентного класса Family". Предыдущее предложение кажется полной абракадаброй, если не проникнуться терминологией объектно-ориентированного программирования. Рассматривайте его как своеобразное словесное упражнение по краткому курсу ООП.

#include <vcl/dstring.h> #include <stdio.h> class Family // объявление класса

{

private:

AnsiString FNames[10]; // массив имен AnsiString GetName(int Index); // метод чтения void SetName(int, AnsiString); // метод записи public:

_property AnsiString Names[int Index] =

{read=GetName, write=SetName} ;

Family(){} // .конструктор -Family(){) // деструктор

};

AnsiString Family::GetName(int i)

{

return FNames[i]; // GetName возвращает значение }

void Family::SetName(int i, const AnsiString s) { FNames[i]=s; // SetName присваивает значение

}

void main()

{

Family My Family; // создание объекта MyFamily // Инициализация 4-х строк массива имен методом SetName() MyFamily.Names[0]="Иван" ;

MyFamily.Names[1]="Анна" ;

MyFamily.Names[2]="Марья";

MyFami ly. Names [ 3 ] = " Андрей " ;

// Вывод 4-х строк массива имен методом GetName() for (int i=0; i<=3; i++)

puts(MyFamily.Names[i].c_str()) ;

}

Листинг 3.18. Пример использования типа AnsiString в C++ программе с компонентным классом Family (Семья).

Variant служит для спецификации значений, меняющих тип динамически. Переменная вариантного типа, в отличие от обычных статически типизированных переменных, способна менять свой тип во время исполнения программы. C++Builder объявляет этот тип Delphi как class __declspec(delphireturn) Variant: public TVarData. Заметим, чтс синтаксис вариантов, принятый в Delphi, например:

V: Variant;

V := VarArrayCreate([0,Hi9hVal,0,HighVal],varlnteger) ;

отличается от способа записи вариантного массива в C++Builder:

Variant V(OPENARRAY(int,(0,HighVal,0,HighVal)),varlnteger);

Вариант может быть сконструирован из следующих типов данных: short, int, float, double. Currency, TDateTime, bool, WordBool, Byte, AnsiString&, char *, wchar_t * const. 01e2::lDispatch* const или 01e2::IUnknown* const. Компилятор автоматически выполнит необходимые преобразования типа. При создании вариантных переменных они всегда инициализируются специальным значением Unassigned (не определено). Специальное значение Null указывает, что данные отсутствуют.

Внимание: Варианты предоставляют ООП чрезвычайную гибкость, однако требуют большей памяти, нежели статически типизированные переменные, а операции над ними выполняются заметно медленнее.

TDateTime используется для спецификации переменных даты и времени. C++Builder реализует этот встроенный тип Delphi как одноименный класс, который инкапсулирует член данных типа double, содержащий значение даты в целой части числа, а значение времени в мантиссе (считая от полудня 30 декабря 1899 года). В следующей таблице приведены значения переменной типа TDateTime и их эквиваленты в выражениях даты и времени:Значение Дата Время Примечания

0 12/30/1899 12:00 +0 дней, +0 часов

2.75 01/01/1900 18:00 +2 дня, +6 часов

-1.25 12/29/1899 06:00 -1 день, -б часов

35065 01/01/1996 12:00 +35065 дней, +0 часов

Чтобы вычислить дробное число дней, прошедших между двумя датами, вычтите второе значение из первого. Чтобы перейти к следующему дню, сохранив время, просто добавьте 1 к текущему значению.

3.6.2 Расширения стандарта ANSI C++

Рассматриваемые расширения стандарта ANSI C++, в основном, представляют интерес для разработчиков новых классов и компонент, а также для программистов, которые работают в большом коллективе над созданием сложного проекта.

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

3.6.2.1 Шаблоны

Шаблоны (параметризованные типы)позволяют конструировать семейство связанных функций или классов. Обобщенный синтаксис определения шаблона имеет вид

template <список шаблонных типов> { объявление } ;

Различают шаблоны функций и шаблоны классов.

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

template <class Т> Т тах(Т х. Ту) { return (x > у) ? х : у; } ;

причем тип данных, представленный аргументом шаблона <class T>, может быть любым. При его использовании в программе компилятор генерирует код функции тах в соответствии с фактическим типом передаваемых ей параметров:

int i;

Myclass a, b;

int j = max(i, 0); // тип аргументов int Myclass m = max(a, b); // тип аргументов Myclass

Фактические типы должны быть известны во время компиляции. Без шаблонов пришлось бы многократно перегружать функцию max - для каждого поддерживаемого типа, хотя код всех версий функции по существу был бы идентичным. Стандарт C++ настоятельно не рекомендует использовать для этой цели макрос:

#define max(x,y) ((х > у) ? х : у) из-за блокировки механизма проверки типов, который дает такие преимущества языку C++ над обычным С. Очевидно, задача функции тах(х, у) - сравнить совместимые типы. К сожалению, использование макроса допускает сравнение несовместимых типов, например, int и struct.

Шаблон классов задает образец определений семейства классов. Рассмотрим пример шаблона Vector - генератора классов одномерного массива данных:

template <class T> class Vector

Над типизированными элементами этого класса выполняются одинаковые базовые операции (вставить, вычеркнуть, индексировать и т.д.), вне зависимости от конкретного типа элементов. Если обращаться с типом как с параметром, то компилятор будет генерировать классы векторов с элементами заданного типа.

Как и в случае шаблонов функций, разрешается явно переопределять тип шаблон классов:

class Vector<char *> ( ... };

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