- •Раздел 4. Разработка по Тема 4.1. Проектирование интерфейса с пользователем
- •4.1.1. Типы пользовательских интерфейсов.
- •4.1.2. Пользовательская и программная модели интерфейса.
- •4.1.3. Разработка диалогов.
- •4.1.4. Основные компоненты графических пользовательских интерфейсов.
- •Тема 4.2. Реализация графических пользовательских интерфейсов.
- •4.2.1. Диалоги, управляемые пользователем.
- •4.2.2. Диалоги, управляемые системой.
- •4.2.3. Использование метафор.
- •4.2.4. Технология Drag and Drop.
- •4.2.5. Интеллектуальные элементы.
- •4.3.1. Базовые типы данных.
- •Константы
- •Область действия имен
- •4.3.2. Указатели и адресная арифметика.
- •4.3.3. Составные типы данных. Структуры
- •Битовые поля
- •Определение типов
- •Перечислимые типы
- •4.3.4. Выражения и операции.
- •4.3.5. Управляющие конструкции. Условные операторы
- •Операторы циклов
- •4.4.1. Статические одномерные массивы.
- •4.4.2. Статические многомерные массивы.
- •4.4.3. Динамические массивы.
- •4.4.4. Массивы указателей.
- •4.5.1. Стеки.
- •4.5.2. Очереди.
- •4.5.3. Списки.
- •4.5.4. Бинарные деревья.
- •4.6.1. Объявление классов и экземпляров классов.
- •4.6.2. Инкапсуляция данных и методов.
- •4.6.3. Конструкторы классов.
- •Конструктор по умолчанию
- •Конструктор копирования
- •4.6.4. Деструкторы классов.
- •4.7.1. Разделы в описании класса.
- •4.7.2. Friend-конструкции.
- •4.7.3. Статические члены классов.
- •4.7.4. Использование описателя const в классах.
- •4.8.1. Вложенность классов.
- •4.8.2. Наследование данных и методов.
- •4.8.3. Типы наследования.
- •4.9.1. Полиморфизм раннего связывания.
- •4.9.2. Полиморфизм позднего связывания и виртуальные функции.
- •4.9.3. Абстрактные методы и классы.
- •4.10.1. Функции консольного ввода-вывода.
- •4.10.2. Функции файлового ввода-вывода.
- •4.10.3. Использование библиотеки классов потокового ввода-вывода.
- •4.11.1. Перегрузка операций.
- •4.11.2. Шаблоны функций.
- •4.11.3. Шаблоны классов.
- •4.11.4. Обработка исключений.
- •Тема 4.12. Com-технология.
- •4.12.1. Основные понятия.
- •4.12.2. Типы интерфейсов.
- •Свойства интерфейсов
- •Типы интерфейсов
- •4.12.3. Типы com-объектов.
- •4.12.4. Фабрика классов.
- •Тема 4.13. Построение com-сервера.
- •4.13.1. Язык idl.
- •Содержимое файла idl
- •4.13.2. Определение пользовательского интерфейса.
- •4.13.3. Реализация пользовательского интерфейса.
- •4.13.4. Создание тестового клиента.
- •Тема 4.14. Обзор платформы ms .Net.
- •4.14.1. Общая идея архитектуры .Net.
- •4.14.2. Достоинства и недостатки .Net.
- •4.14.3. Схема трансляции программ в .Net.
- •4.14.4. Язык msil.
- •4.14.5. Объектно-ориентированная модель .Net.
4.7.1. Разделы в описании класса.
Приведем обобщенную схему описания класса:
class Class_Name {
private:
// Здесь расположены данные и методы, которые недоступны
// извне обычным, прямым способом. Они доступны только в
// методах класса Class_Name, а с их помощью и извне
protected:
// Здесь расположены данные и методы, недоступные прямо.
// Они доступны в методах класса и в методах производных
// классов. Последние будут рассмотрены ниже
public:
// Здесь расположены данные и методы, доступные обычным,
// прямым способом из внешних процедур
};
Тела методов могут быть приведены как внутри каждого из разделов класса, так и вне всего блока описаний, в том числе и в другом файле.
ЗАМЕЧАНИЕ ————————————————————————————————
При отсутствии описателей private, protected и public члены класса по умолчанию имеют тип private. Для структур и union-структур все члены по умолчанию, наоборот, имеют тип public.________________________________________________________________________
Язык C++ временно допускает неполную декларацию класса (incomplete declaration). Например:
class А; //Неполная декларация класса А
class В { А *ра; }; // Указатель на класс А — член класса В
class А { В *pb;}; // Класс А декларирован полностью
// Возможные объявления переменных класса А
A obj; // Объект класса А
А *р; // Указатель на объекты класса А
A &ref = obj; // Ссылка на класс А
А аrrау[7]; // Массив объектов класса А
A func(); // Функция, возвращающая объект класса А
Декларировать можно объекты, указатели и ссылки на класс, массивы o6ъектов класса, функции, возвращающие объект класса. Напомним: чтобы послать объекту сообщение, имея только его адрес (р), используется операция выбоpа p->method(). Таким образом, эквивалентны три способа инициации метода класса:
class А { public: void method () { printf ("\nOk"):; } };
void main()
{
A *p, obj; // Указатель и объект класса А p=&obj; // р указывает на obj //----- Три способа вызова функции ---------//
obj.method(); // Сообщение объекту (&obj)->method(); //То же, но с помощью адреса p->method(); // То же, но с помощью указателя }
Заметим, что во втором способе: (&obj)->method() скобки обязательны, так как приоритет операции выбора с помощью указателя выше, чем операции взятия адреса.
Как правило, перед использованием объект должен быть инициализирован. В С этот процесс выполнялся либо автоматически (для глобальных и статических элементов), либо путем определения специальной функции, которая вызывается сразу после создания объекта, до его использования. Аналогичный подход можно использовать и в С++. Однако в нем предусмотрен способ лучше.
4.7.2. Friend-конструкции.
Напомним, что private-данные и методы какого-либо класса прямо доступны только внутри методов класса. Эта ограниченная доступность, с одной стороны, предлагает выгоды, которые предоставляют инкапсуляция и скрытие данных, с другой стороны, накладывает значительную ответственность, так как необходимо обеспечить каждый класс достаточным количеством методов для манипуляции данными во всех реально встречаемых ситуациях. C++ имеет способ обойти это жесткое ограничение и позволить избранным внешним классам, отдельным методам класса или обычным внешним функциям прямой доступ ко всем данным класса, в том числе и к private. Самое простое — это объявить обычную функцию (не являющуюся членом какого-либо класса) friend-функцией класса. Теперь она имеет доступ ко всем данным и методам класса и может модифицировать private-данные класса. Например:
class A {
private:
int i; // private-данное
friend void set (A*, int); // friend-функция
public:
void set (int j) { i=j; } // public-метод
void p() { printf("\n i=%d”,i);}
};
void set (A* p, int i) // Тело friend-функции
{
p->i=i;
}
void main()
{
A obj; // Объект obj класса А
set (&obj, 10); //Доступ с помощью friend-функции
obj.p(); // Вывод поля
obj.set (11); // То же, но с помощью public-метода
obj.p();
}
В примере объявлена внешняя функция set. Она не принадлежит никакому классу. Но она, будучи объявленной friend-функцией класса А, имеет прямой доступ к private-переменной класса А, так же, как и метод set собственного класса. Указатель (или ссылку) на объект класса А следует передать в качестве параметра, так как friend-функция является посторонней функцией и не знает объекта obj класса А (в отличие от метода void A::set(int); класса, которому неявно передается указатель this). При вызове внешней функции мы передаем ей &obj — адрес объекта. Этот адрес присваивается локальному указателю р, после чего выражение p->i позволяет обратиться к private-переменной объекта, на который ссылается указатель р. Поле объекта obj прямо доступно внутри friend-функции set. Отметим, что эти же действия можно было осуществить, используя передачу ссылкой. При этом вызов функции должен быть set (obj,10):, ее прототип — friend void set(A&, int);, сама функция — void set (A& a, int i) { a.i=i; }.
Friend-функция может принадлежать какому-либо другому классу. Тогда ее можно назвать friend-методом. Чтобы сократить время доступа метода класса В к методу класса А, целесообразно объявить в классе А конкретный метод класса В как friend-метод класса А. Кроме того, в классе А можно объявить весь класс В как friend-клacc класса А. Теперь все методы класса В являются friend-методами класса А, то есть внутренние данные класса А теперь прямо доступны в методах класса В. Объявление friend-конструкций может быть размещено в любой секции (private, protected, public) описания класса. Это не влияет на смысл объявления. Следующая схема иллюстрирует рассмотренные возможности:
class A{
friend int strange(char* ch); // Friend-функция
friend class B; // Friend-класс
friend char* C::methc(); // Friend-метод класса С
};
Свойство friend не транзитивно, то есть если класс В объявлен friend-классом в классе А, а класс С — в классе В, то это не означает, что класс С является friend-классом для класса А («друг моего друга — не мой друг»). При создании производных классов (что будет рассмотрено ниже) следует помнить, что свойство friend не наследуется.