на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Препроцессорные средства в C и С++
p align="left"> TIntArray& subtract(TIntArray&); // Вычитание массивов

void printElem(int index); // Вывод значения элемента на экран

void print(); // Вывод на экран всего массива

TIntArray(int m,int d):TBase((int)sizeof(int),m,d){ }; /*Конструктор */

TIntArray(TBase& a):TBase( a ){}; /*Конструктор */

~TIntArray();

};

Определения методов приведены в файле TBASEARR.CPP:

#include <iostream.h>

#include <stdlib.h>

#include <constrea.h>

#include <tbasearr.h>

/* Методы класса TBase */

TBase::TBase(int s,int m,int d):size(s),maxCount(m),delta(d)

{char* p;

int k;

count = 0; p = pmem = new char [size * maxCount];

for (k=0; k < maxCount; k++)

{ *p = '\0'; p++;}

}

TBase::TBase():size(1),maxCount(10),delta(1)

{char* p;

int k;

count = 0; p = pmem = new char [size *maxCount];

for (k=0; k < maxCount; k++)

{ *p = '\0'; p++;}

}

TBase::TBase(TBase& b):size(b.size),maxCount(b.maxCount),delta(b.delta)

{ int k;

count = b.count; pmem = new char [size * maxCount];

for (k=0; k < maxCount * size; k++)

{ pmem[k] = b.pmem[k];}

}

TBase::~TBase ()

{ delete [ ] pmem; }

4.5 Виртуальные функции

4.5.1. Понятие о “позднем” связывании

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

4.5.2. Описание виртуальных функций

Функция-компонента класса объявляется как виртуальная указанием ключевого слова virtual. Функции-компоненты в производных классах, заменяющие виртуальную функцию базового класса должны объявляться с тем же именем, тем же списком параметров и типом возвращаемого значения, что и соответствующая функция базового класса. Если из производного класса не образуется новых производных классов, ключевое слово virtual в описании функции можно опустить.

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

Виртуальная функция может быть объявлена в форме:

virtual void print ( ) = 0;

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

Виртуальные функции особенно полезны, когда к методом класса требуется обращаться через указатель на экземпляр класса, а сам этот указатель имеет тип указателя на базовый класс. Пусть, например, в классе TBase объявлена чистая виртуальная функция print:

class TBase //базовый класс для массивов всех типов

{int size, //размер элемента

count, //текущее число элементов

maxCount, //размер выделенной памяти в байтах

delta; //приращение памяти в байтах

char *pmem; //указатель на выделенную память

int changeSize(); //перераспределение памяти

protected:

void* getAddr( ){return (void*) pmem;};

void addNewItem(void*); //добавление в конец массива

void error(const char* msg){cout <<msg<<endl;};

public:

int getCount() {return count;};

TBase(int s,int m,int d);

TBase();

TBase(TBase&);

~TBase();

virtual void print ( ) = 0; // Чистая виртуальная функция

};

Тогда в производных классах должна быть объявлена замещающая ее функция print, выполняющая реальные действия:

class TIntArray : public TBase

{ /* Другие методы */

virtual void print ( );

}

class TRealArray : public TBase

{ /* Другие методы */

virtual void print ( );

}

В программе, использующей объекты классов TIntArray и TRealArray могут создаваться экземпляры этих классов с возможностью обращения к ним через указатель на базовый класс:

TBase *pb;

TIntArray aint(5,3);

TRealArray areal(4,2);

Тогда для печати массивов могут применяться операторы

pb = &aint; pb->print(); //Печать массива aint

pb = &areal; pb->print(); // Печать массива areal

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

Программа:

#include <iostream.h>

struct Pet // Базовый класс

{ char *name;

virtual void speak() = 0;

Pet( char *nm){name=nm;}

}

struct Dog : public Pet

{ virtual void speak( ) { cout<<name<<“ говорит “”<<“ Ав - ав”<<endl; };

Dog(char *nm): Pet(nm) { };

};

struct Cat : public Pet

{ virtual void speak( ) { cout<<name<<“ говорит “

<<“ Мяу-Мяу”<<endl;

Cat(char *nm): Pet(nm) { };

}

int main ()

{ Pet *mypets[ ] = { new Dog(“Шарик”),

new Cat(“Мурка”),

new Dog(“Рыжий “)}; // Список животных

const int sz = sizeof( mypets)/ sizeof( mypets [ 0 ]);

for ( int k = 0: k < sz; k++)

mypets [ k ]->speak();

return 0;

}

4.6. “Дружественные” (friend) функции

Функция, объявленная в производном классе, может иметь доступ только к защищенным (protected) или общим (public) компонентам базового класса.

Функция, объявленная вне класса, может иметь доступ только к общим (public) компонентам класса и обращаться к ним по имени, уточненному именем объекта или указателя на объект.

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

class X

{ friend void Y:: fprv( int, char*);

/* Другие компоненты класса X */

}

Можно объявить все функции класса Y дружественными в классе X;

class Y;

class X

{ friend Y;

/* Другие компоненты класса X */

}

class Y

{ void fy1(int, int);

int fy2( char*, int);

/* Другие компоненты класса Y */

}

Дружественной может быть и функция, не являющаяся компонентой какого-либо класса, например,

class XX

{ friend int printXX ( );

/* Другие компоненты класса ХХ */

}

Здесь функция printXX имеет доступ ко всем компонентам класса XX, независимо от закрепленного за ними уровня доступа.

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

4.7. Статические компоненты класса

Описатель static в С++ имеет различное назначение в зависимости от контекста, в котором он применен.

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

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

Компоненты класса также могут объявляться с описателем static, такие компоненты - данные являются общими для всех экземпляров объектов этого класса и размещаются в памяти отдельно от данных объектов класса. Доступ к static - компонентам класса возможен по имени, уточненному именем класса (именем типа) или именем объекта этого класса, причем к static - компонентам класса можно обращаться до создания экземпляров объектов этого класса. Статическое данное - член класса должно быть обязательно инициализировано вне описания класса:

class TBase //базовый класс для массивов всех типов

{ static int nw;

int size, //размер элемента

count, //текущее число элементов

maxCount, //размер выделенной памяти

delta; //приращение памяти

/* Другие компоненты класса TBase */

}

int TBase::nw =1; /* Инициализация статической компоненты класса */

Статические компоненты - функции могут вызываться до создания экземпляров объектов этого класса и поэтому имеют доступ только к статическим данным класса:

class X

{ static int sx1,sx2;

static void fsx ( int k);

int x1,x2;

/* Другие компоненты класса X */

}

int X::sx1 = 1;

int X::sx2 = 2;

int main ()

{ ..........

X:: fsx( 3 );

..............

}

4.8. Переопределение (перегрузка) операций

В языках программирования определена семантика операций, выполняемых над базовыми (предопределенными) типами данных, например, если x, y и z - переменные типа float, то запись x = y + z; предполагает интуитивно очевидные действия, сложение x и y и присваивание переменной z полученной суммы.

Желательно было бы и для типов, определяемых в программе, в том числе для классов, определить семантику и алгоритмы операций сложения, вычитания, умножения и т.д., чтобы иметь возможность вместо вызова соответствующих функций записывать просто x + y и в случае, когда x и y являются объектами некоторых классов. В C++ это достигается переопределением имеющихся в языке операций для других типов данных.

Переопределенная операция объявляется так:

тип_результата operator знак_операции (формальные параметры)

{ описание_алгоритма_выполнения_операции }

Например:

class TPoint

{ int x,y;

Страницы: 1, 2, 3, 4, 5, 6



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.