Абстрактные классы и виртуальные функции
Цель работы – освоить разработку иерархии классов с виртуальными функциями, основанной на абстрактном базовом классе (4 час.).
Задание
1. По конспекту лекций освежите в памяти абстрактные и виртуальные функции, а также абстрактные классы.
2. Ознакомьтесь с приведенными ниже методическими указаниями.
3. Создайте заготовку консольного приложения.
4. В соответствии с вашим вариантом задания разработайте иерархию классов, добавьте их в приложение. Базовый класс вашей иерархии должен содержать конструктор с параметрами и минимум одну абстрактную функцию; производные классы должны содержать реализацию абстрактной функции (функций) и конструкторы с параметрами.
5. Опишите указатели на абстрактный класс, создайте с их использованием объекты производных классов иерархии, вызовите методы классов и убедитесь в том, что механизм виртуальных функций работает корректно и объекты действительно полиморфны. Методы полиморфных объектов вызывайте в глобальных функциях, как показано ниже в методических указаниях.
Методические указания
В качестве иллюстрации разработаем иерархию классов (рис. 1) и поместим ее реализацию в файлы Base.h и Base.cpp (проект ACVF).
|
// Файл Base.h
#pragma once
Class CBase
{
public:
virtual char * getName()=0;
};
Class CFirst: public CBase
{
double *dFoo;
public:
virtual char * getName();
CFirst();
~CFirst();
};
Class CSecond: public CFirst
|
|
{
int *iFoo;
public:
CSecond();
~CSecond();
virtual char * getName();
};
Рис. 1. Иерархия классов
Реализацию методов класса поместим в файл Base.cpp и добавим в конструкторы и деструкторы вывод сообщений об их вызове. Для вывода сообщений можно было бы использовать макросы TRACE, но в данном случае мне показалось удобнее использовать для вывода cout.
// Файл Base.cpp
#include "StdAfx.h"
#include "Base.h"
using namespace std;
CBase::~CBase()
{
cout<<"CBase::~CBase"<<endl;
}
CFirst::CFirst()
{
dFoo=new double [100];
cout<<"CFirst::CFirst"<<endl;
}
CFirst::~CFirst()
{
cout<<"CFirst::~CFirst"<<endl;
delete [] dFoo;
}
CSecond::CSecond()
{
cout<<"CSecond::CSecond"<<endl;
iFoo=new int [100];
}
CSecond::~CSecond()
{
cout<<"CSecond::~CSecond"<<endl;
delete [] iFoo;
}
char * CFirst::getName()
{return "CFirst";}
char * CSecond::getName()
{return "CSecond";}
Для проверки виртуальных функций разработаем глобальные функции, которые получают объекты классов иерархии в качестве параметров:
void PrintClassNamе1(CBasе *pb) // параметр-указатель
{
сout<<pb->gеtNamе()<<еndl;
}
void PrintClassNamе2(CBasе &b) // параметр-ссылка
{
сout<<b.gеtNamе()<<еndl;
}
Void PrintClassNamе3(CFirst f) // параметр-значение
{
сout<<f.gеtNamе()<<еndl;
}
Теперь поместим в главную функцию код, который позволит испытать полиморфные объекты иерархии:
|
|
int _tmain(int argс, TCHAR* argv[], TCHAR* еnvp[])
{
//...
CBase *obj;
obj=new CFirst; // вывод CFirst::CFirst
cout<<endl;
PrintClassName1(obj); // выводит CFirst
cout<<endl;
PrintClassName2(*obj); // выводит CFirst
cout<<endl;
delete obj; //Вывод CBase::~CBase!! Деструктор ~CFirst не вызван!
cout<<endl;
obj=new CSecond; // вывод CFirst::CFirst CSecond::CSecond
PrintClassName1(obj); // выводит CSecond
cout<<endl;
delete obj; //Вывод CBase::~CBase!! Деструкторы ~CSecond и ~CFirst
// не вызваны!
CFirst * fobj=new CSecond; // вывод CFirst::CFirst CSecond::CSecond
cout<<endl;
PrintClassName1(fobj); // выводит CSecond
cout<<endl;
PrintClassName2(*fobj); // выводит CSecond
cout<<endl;
PrintClassName3(*fobj); // выводит CFirst, затем CFirst::~CFirst
// и CBase::~CBase
cout<<endl;
delete fobj; /* Вывод CFirst::~CFirst, после чего программа снимается
Дата добавления: 2018-02-18; просмотров: 482; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!