Литература
1. Коннолли, Томас, Бегг, Каролин. Базы данных. Проектирование, реализация и сопровождение. Теория и практика. 3-е издание. : Пер. с англ. - М. : Издательский дом "Вильямс", 2003. - 1440 с. : ил. - Парал. тит. англ.
2. Дейт К. Дж., Введение в системы баз данных, 7-е издание. : Пер. с англ. - М. : Издательский дом «Вильямс», 2001. - 1072 с. : ил. - Парал. тит. англ.
3. Мюллер Р. Дж., Базы данных и UML проектирование: Пер. с англ. - М. : Лори, 2002. - 420с.: ил. - Парал. тит. англ.
УДК 004.43:378.09
ПОЛИМОРФИЗМ И ИСПОЛЬЗОВАНИЕ ВИРТУАЛЬНЫХ ФУНКЦИЙ
Мясникова Нелли Александровна, доцент, Южно-Российский государственный технический университет (Новочеркасский политехнический институт), Россия, Новочеркасск, [email protected] Шепилов Владислав Александрович, студент, Южно-Российский государственный технический университет (Новочеркасский политехнический институт), Россия, Новочеркасск, [email protected]
Для построения иерархий классов в любом языке программирования высокого уровня должен быть реализован механизм полиморфизма, который обеспечивает возможность определения разнообразных аспектов некоторого единого метода по названию для классов разных уровней иерархии. Также различают простой полиморфизм, который базируется на механизме раннего связывания, и сложный полиморфизм, который использует механизм позднего связывания.
Простой (еще называют статический) полиморфизм поддерживается языком C++ на этапе компиляции (так называемое раннее связывание) и реализуется с помощью механизма переопределения функций. Такие полиморфные функции в C++ называют переопределяемыми, в соответствии с общими правилами, они могут отличаться типом возвращаемого параметра и сигнатурой.
Такой подход позволяет строить более гибкие и совершенные иерархии классов, заменяя в производных классах методы. Чтобы показать использование статического полиморфного метода рассмотрим пример 1. В нем функция print() является статическим полиморфным методом. Функция show(), вызывает метод print() и наследуется в производных классах.
Пример 1. Использование раннего связывания
#include < iostream. h>
#include <conio.h> class A {
int a; public: void show()
{
cout<<"Содержимое полей объекта"<<endl;
print ();
} //вызов статической полиморфной функции void print(void)
// первый аспект статической полиморфной функции {
cout<<a<<endl;
}
A(int v):a(v){}
};
class В: public А
64
{
int b; public:
void print(void) // второй аспект статической полиморфной функции {
cout<<b<<endl;
}
B(int va, int vb):A (va), b(vb) {}
};
class C: public В {
int с; public:
void print(void) //третий аспект статической полиморфной функции {
cout<<c<<endl;
}
^int va, int vb, int vc) :B(va, vb), c(vc) {}
};
void main()
{
clrscr();
A aa(20); В bb(10,100); С cc(50,200,3000); cout<<" Результаты работы: "<<endl;
// явный вызов полиморфной функции print()
aa.print(); // выводит: 20
bb.print(); //выводит: 100
cc.print(); // выводит: 3000
getch();
// неявный вызов полиморфной функции print()
aa.show(); // выводит: 20
bb.show(); //выводит: 10
cc.show(); // выводит: 50
getch();
}
Несложно заметить, что результаты явного и неявного вызовов метода print() различаются. Это связано с тем, что метод show(), который наследуется в производных классах, вызывает метод print(). При раннем связывании show() жестко соединяется с этим методом на этапе компиляции. Поэтому вне зависимости от того, объект какого класса вызывает метод show(), из него будет вызван метод print() базового класса, для которого внутренние поля производных классов недоступны. Это и является главной отличительной чертой раннего связывания.
Чтобы получить правильный результат в подобных случаях, нужно использовать сложный полиморфизм. Сложный полиморфизм можно реализовать с помощью механизма позднего связывания, что требует описания виртуальных функций.
Виртуальные функции - это такие функции, которые объявляются с использованием ключевого слова virtual в базовом классе и замещаются в одном или нескольких производных классах. В этом случае прототипы функций в разных классах должны совпадать по именам, типу возвращаемого результата, сигнатуре. Алгоритмы, реализуемые такими функциями, различаются между собой. В случае, когда типы функций различны, механизм виртуальности для них не включается.
Также стоит заметить, что виртуальную функцию в языке C++ принято называть «полиморфной», что не в полной мере соответствует общепринятой терминологии, по общепринятой терминологии она является «динамической полиморфной».
В качестве иллюстрации рассмотрим пример 2, который является модификацией предыдущего.
65
Пример 2. Использование виртуальных функций
#include <iostream.h>
#include <conio.h> class A {
int a; public: void show()
{
cout<<"Содержимое полей объекта"<<endl;printO;
}
virtual void print(void) // описание виртуальности функции {
cout<<a<<endl;
}
A(int v):a(v){}
};
class B: public A {
intb;
public:
void print(void) // первый аспект виртуальной функции {
cout<<b<<endl;
}
В (int va, int vb) :A (va), b(vb) {}
};
class C: public В {
int с; public:
void print(void) // второй аспект виртуальной функции {
cout<<c<<endl;
}
C(int va, int vb, int vc) :B(va, vb), c(vc) {}
};
void main()
{
clrscr();
A aa(10), *pa; // указатель на объект базового класса
В bb(10,100);
C cc(10,100,1000);
cout<<" Результаты работы: "<<endl;
cout<<'' Явный вызов полиморфной функции print(): "<<endl;
aa.print(); //выводит: 10
bb.print(); //выводит: 100
cc.print(); //выводит: 1000
getch();
cout<<" Неявный вызов полиморфной функции print(): "<<endl;
aa.show(); //выводит: 10
bb.show(); //выводит: 100
cc.show(); //выводит: 1000
getch();
cout<<"Вызов функции print() по указателю"<<endl;
ра=&аа; pa->prmt(); //выводит: 10
pa=&bb; pa->print(); //выводит: 100
ра=&сс; pa->print(); //выводит: 1000
getch();
}
66
Как мы видим, каждый раз вызывается нужная версия виртуальной функции.
Функция, которая была объявлена виртуальной, остается ею, сколько бы производных классов ни образовывалось. Но иногда в одном или нескольких производных классах переопределение виртуальной функции может отсутствовать. Тогда механизм подключения виртуальной функции сохраняется и вызывается функция класса, которая ближе к рассматриваемому классу. Если будет отсутствовать аспект виртуальной функции, это не нарушит механизм позднего связывания, и если у наследников такого класса появится аспект виртуальной функции, он будет вызываться без каких-либо нарушений.
Литература
1. Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на C++. - М.: Бином; СПб.: Невский диалект, 2001. - 560 с.
2. Бьерн Страуструп. Язык программирование C++. М.: Бином, 2001. - 1099 с.
3. Г. С. Иванова. Объектно-ориентированное программирование. - МГТУ им. Н. Э. Баумана, 2002.
4. Курс: Основы информатики и программирования. Лекция №10: Основы объектно-
ориентированного программирования. Применение ООП к разработке программных проектов. Основные концепции ООП, www.intuit.ru/department/se/oip/10/
УДК 004.652.5
ОБЪЕКТНАЯ БАЗА ДАННЫХ ДЛЯ СТУДЕНТОВ
Неудачин Илья Георгиевич, к.ф.-м.н., доцент, Уральский федеральный университет имени первого Президента России Б.Н.Ельцина, Россия, Екатеринбург, [email protected]
Введение
ZODB (Zope Object DataBase) - система хранения объектов приложений, написанных на языке Python. Она обеспечивает язык программирования средствами, которые автоматически записывают объекты на диск и читают их снова, когда они требуются программой. Установка ZODB добавляет такие средства к Python. Пакет ZODB выделен из инфраструктуры разработки и Web-публикации объектов Zope [1, 2], для которой - это стандартная объектная база данных (ОБД). Изучая ОБД, студенты осваивают разнообразие архитектур баз данных. Так же как Python и Zope, ZoDB поставляется в открытых кодах (http://old.zope.org/Products/ZODB3.2), бесплатно и с лицензией, благоприятной для ее модификации студентами и дальнейшего применения.
1. Подробное описание инструментария
К выбору ZODB как предмета обучения приводят три основные причины. Во-первых, ZODB - открытый продукт. Что позволяет студентам, при желании, не только видеть, как что-то работает, но понимать, как это работает. Во-вторых, использование ZODB бесплатное. Это позволяет изучать, исследовать и приобретать опыт без больших расходов. В-третьих, можно изменять коды ZODB. Она интересна как пользователям и администраторам, так и тем, кто программирует на языке Python. Описываемый учебный материал частично применяется при подготовке студентов - бакалавров профиля «Вычислительные машины, комплексы, системы и сети: системная интеграция». ОБД дала логическую связку между учебными разделами программирования на языке Python и проектированием динамических Web-приложений в инфраструктуре Zope [3].
В ZODB хранится не только объект, но и его текущее состояние, информация о нём, а также как он используется. Т.е. запоминаются действия пользователя, что допускает отмену пользователем этих действий. ZODB поддерживает транзакции, версии, откат и, как следствие, - упаковку завершенных транзакций и версий. Эта мощная объектная система баз данных, которая может использоваться с Zope или без Zope.
67