Абстрактные классы и виртуальные функции



Цель работы – освоить разработку иерархии классов с виртуальными функциями, основанной на абстрактном базовом классе (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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!