Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
40
Добавлен:
16.02.2016
Размер:
382.98 Кб
Скачать

1. ОБЪЕКТНО ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ НА C++

Среда программирования Microsoft Visual C++ позволяет разрабатывать приложения как в терминах традиционного модульного программирования, так и с применением объектно ориентированного программирования.

В этой главе будут рассмотрены некоторые наиболее общие элементы языка C++, применяемые как при традиционном модульном программировании, так и при программировании в терминах классов и с применением библиотеки MFC.

Структура приложения

Приложение может состоять из одного или нескольких модулей трансляции. Модулями трансляции называются файлы исходного кода на языке C++. В терминологии Visual C++ совокупность всех модулей трансляции (файлов реализации классов и заголовочных файлов), файлов ресурсов и описание конфигурации называется проектом.

Среда проектирования VISUAL STUDIO 98 автоматически поддерживает информацию о структуре проекта. Весь проект представляется как некоторая иерархия классов: для каждого класса по два файла - заголовочный файл и файл реализации. Более подробно работа с проектами будет рассмотрена в следующей главе.

Терминология объектно-ориентированного программирования

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

Класс является некоторым расширением типа struct языка C++. Класс имеет данные (переменные) и поведение (методы). Данные и методы класса также называют членами класса.

Объектом называется экземпляр некоторого класса.

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

А Базовый класс класса С и непосредственный базовый класс класса

D

D Непосредственный базовый класс класса С

С Производный класс

Наследование позволяет определить новые классы в терминах существующих классов, наследование может быть единичным и множественным. При единичном наследовании производный класс может иметь только один непосредственный базовый класс. Таким образом построена библиотека классов MFC. При множественном наследовании производный класс может иметь несколько непосредственных базовых классов.

Полиморфизмом называется способность различных объектов по-разному обрабатывать одинаковые сообщения.

Инкапсуляция позволяет работать в терминах объектов и скрывать их переменные и методы. Использование инкапсуляции дает возможность модифицировать внутреннюю реализацию объекта без какого-либо влияния на программу в целом до тех пор, пока не будет затронут интерфейс с объектом (доступные методы и переменные). Инкапсуляция обеспечивается модификаторами доступа public, protected и private, а также использованием дружественных методов и классов.

Объявление класса

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

class type_classname : baseclassname_list {

type1 var1;

type2 var2;

...

typen varn;

public:

metod1();

...

protected:

metodi();

...

private:

}

// baseclassname_list - список базовых классов разделенный запятыми: public ClassA, public ClassB, private ClassC

При объявлении производного класса после имени класса через символ двоеточия (:) указывается список базовых классов. Можно для каждого базового класса указать модификатор доступа. Если модификатор доступа не указан, то по умолчанию предполагается, что класс имеет модификатор доступа protected (защищенный доступ).

Модификатор доступа, указываемый перед именем базового класса, определяет следующие правила доступа к переменным и методам базового класса из производного класса:

  • public - в производном классе доступны все переменные и методы базового класса с модификаторами доступа public и protected и имеют те же права доступа;

  • protected - члены базового класса с модификаторами public и protected доступны как protected, с модификатором private - недоступны;

  • private - члены базового класса с модификаторами public и protected доступны как private, с модификатором private - недоступны.

В теле объявления класса следует указывать модификаторы доступа, описывающие права доступа для переменных и методов класса. Один и тот же модификатор доступа может указываться несколько раз. После модификатора доступа ставится символ двоеточие.

Для того чтобы непосредственно указать метод или переменную какого класса использовать, перед именем метода или переменной проставляется символ ::. Например, CWnd::GetParent().

Для доступа к объекту класса можно использовать ключевое слово this, являющееся указателем на объект данного класса. Это ключевое слово нельзя использовать вне метода члена класса.

Пример:

class A { int i;

public:

mult( int j);}

A:: mult( int j) { return j*this->i; }

Дружественные методы и классы

Дружественные методы позволяют получить доступ к защищенным модификатором private членам класса из методов других классов. Если, метод класса А внутри тела класса В объявляется с модификатором friend, то из него разрешен доступ ко всем членам класса В.

Пример:

class В {

friend A::metod1();

}

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

Пример:

class В {

friend class A;

}

Статические члены класса

Переменные и члены класса, объявленные с модификатором доступа static, называются статическими членами класса. Статические переменные являются общими и создаются в одном экземпляре для всех объектов класса. При этом статические переменные и методы могут быть доступны и без создания объекта. Статические методы могут вызывать и использовать только другие статические методы и статические переменные.

Конструкторы и деструкторы

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

Деструктором называется метод, вызываемый при разрушении объекта данного класса. Имя деструктора совпадает с именем класса и начинается с символа ~.

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

При использовании конструктора базового класса, имеющего параметры, в теле производного класса следует определить конструктор производного класса со списком параметров.

Пример:

// Объявление базового класса

class CAclass {

charsStrl[10];

public:

void lenstrng(char*);

}

// Объявление производного класса CBclass от базового класса CAclass

class CBclass : public CAclass {

char sStr2[10];

public:

void printstr(char*);

}

Вложенные классы

Язык C++ допускает вложенные классы - внутри тела одного класса содержится объявление других классов.

Пример:

// Объявление класса CAclass, содержащего вложенный класс CBclass

class CAclass {

class CBclass {

charsStr2[10];

public:

void printstr(char*);

}

char sStrl[10];

public:

void lenstrng(char*);

}

Виртуальные методы

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

Применение виртуальных методов позволяет реализовывать механизм позднего связывания - определение вызываемого метода происходит на этапе выполнения (а не при компиляции) в зависимости от типа объекта, для которого вызывается виртуальный метод.

На этапе компиляции строится таблица виртуальных методов, а конкретный адрес проставляется уже на этапе выполнения.

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

  • для виртуального метода вызывается метод, соответствующий типу объекта, на который указывает указатель;

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

Следующий пример иллюстрирует применение виртуальных методов, вызываемых через указатель.

class Base // Объявление базового класса

{

public:

virtual void VirtMetod(); // Виртуальный метод

void Metod2(); // Невиртуальный метод

};

// Реализация двух методов

void Base::VirtMetod() { cout « "Base::VirtMetod\n"; }

void Base::Metod2() { cout « "Base::Metod2\n"; }

class Derived : public Base // Объявление производного класса

{public:

void VirtMetodO; // Виртуальный метод

void Metod2(); // Невиртуальный метод

};

// Реализация двух методов

void Derived::VirtMetod() { cout « "Derived::VirtMetod\n";}

void Derived::Metod2() { cout « "Derived::Metod2\n";}

void main()

{

Derived aDerived; // Объект класса Derived

// Инициализация двух указателей указателем на объект класса aDerived

Derived *pDerived = &aDerived; // Указатель на объект класса Derived

Base *pBase = &aDerived; // Указатель на объект класса Base

pBase->VirtMetod(); // Вызов метода VirtMetod класса Derived

pDerived->VirtMetod(); // Вызов метода VirtMetod класса Derived

pBase->Metod2(); // Вызов метода Metod2 класса Base

pDerived->Metod2(); // Вызов метода Metod2 класса Derived

}

Результатом выполнения этой программы будут следующие строки:

Derived::VirtMetod

Derived::VirtMetod

Base::Metod2

Derived::Metod2

Виртуальные классы

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

Шаблоны классов и методов

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

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

Например:

template <class Т> void MetodTempl( Т& а, Т& b )

{ Т с(а); а = b; b = с;}

Шаблоны классов позволяют определить параметризированный тип.

Например:

template <class T, int i> class TempClass

{public:

TempClass( void);

~TempClass( void);

int MemberSet( T a, int b );

private:

TTarray[i];

int arraysize;

};

// Описание членов класса

template <class T, int i>

int TempClass< T, i >::MemberSet( T a, int b )

{

if( ( b >= 0 ) && (b < i))

{ Tarray[b++] = a; return sizeof( a ); }

else

return -1;

}

ТИПЫ ДАННЫХ

Тип данных определяет память, выделяемую под переменную данного типа при ее создании.

C++ поддерживает три вида типов:

  • базовые типы (Fundamental types). Экземпляры этих типов обычно называются переменными. Базовые типы указываются зарезервированными ключевыми словами, и их не надо определять;

  • производные типы (Derived types). Переменные этих типов создаются с использованием как базовых типов, так и типов классов. Это структуры, объединения, указатели, массивы;

  • типы класса (Class types). Экземпляры этих типов называются объектами.

Базовые типы

Базовые типы можно подразделить на три категории: целые, с плавающей точкой и тип void (описывающий пустое множество значений).

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

В следующей таблице приведено описание основных базовых типов языка C++.

Тип

Размер, байт

Диапазон

Описание

char signed char

1

От-128 до 127

Символьный тип. Содержит один символ или строку символов. Каждый символ представляется одним байтом. Компилятор различает как отдельные следующие типы: char, signed char и unsigned char

unsigned char

1

От 0

до 255

Символьный тип. Каждый символ представляется одним байтом (значение в диапазоне от 0 до 255)

short signed short

2

От -32768 до 32767

Целый тип. Сокращенное обозначение типа short int. Длина этого типа вне зависимости от используемого компилятора всегда больше или равна длине значения типа char и меньше или равна длине значения типа int

Unsigned short

2

От 0 до 65535

Беззнаковый целый тип

int signed int

42

От -2147483648 до 2147483647

Целый тип. Длина этого типа вне зависимости от используемого компилятора всегда больше или равна длине значения типа short int

unsigned int

4

От 0 до 4294967259

Беззнаковый целый тип

_intn

n/8

Целый тип, размер в битах которого определяется значением п, и может быть равным 8, 16, 32 или 64 битам

long signed long

4

От -2147483648 до 2147483647

Целый тип. Сокращенное обозначение типа long int

unsigned long

4

От 0 до 4294967259

Беззнаковый целый тип

float

4

От 3.4Е-38 до 3.4Е+38

Тип данных с плавающей точкой

double

8

От 1.7Е-308

до 1.7Е+308

Тип данных с плавающей точкой двойной точности. Длина типа double вне зависимости от используемого компилятора всегда больше или равна длине типа float и короче или равна длине типа long double

long double

8

Тип данных с плавающей точкой двойной точности, длина которого равна длине значений типа double. Типы double и long double имеют одинаковое представление, но компилятор трактует их как различные типы

Соседние файлы в папке VC++Баженова