Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
О.О.П / ооп / 18. Об'єктно-орієнтоване програмування, л.5.5 - 5.8.ppt
Скачиваний:
26
Добавлен:
30.05.2020
Размер:
3.38 Mб
Скачать

class CShape

{

public:

virtual std::string GetType()const=0; virtual double GetArea()const=0; virtual void Draw()const=0;

};

Інтерфейс

Неможливо створити екземпляр абстрактного класу

Всі методи абстрактного класу мають бути реалізовані в похідних класах

Абстрактний клас, що містить лише чисто віртуальні методи ще називають

інтерфейсом

Деструкція такого класу обов'язково має бути віртуальною (не обов'язково чисто віртуальним)

У деяких ОО мовах програмування для оголошення інтерфейсів можуть існувати окремі конструкції мови

Ключове слово слово interface в Java/C#/ActionScript

class IShape

{

public:

virtual void Transform()=0; virtual double GetArea()const=0; virtual void Draw()const=0; virtual ~IShape(){}

};

class CRectangle : public IShape

{

public:

virtual void Transform()

{

...

}

virtual double GetArea()const

{

...

}

virtual void Draw()const

{

...

}

}

class CCircle : public IShape

{

public:

virtual void Transform()

{

...

}

virtual double GetArea()const

{

...

}

virtual void Draw()const

{

...

}

}

Приведення типів

в межах ієрархії

класівПриведення типів вгору за ієрархією завжди можливо і може відбуватися неявно

Всякий собака є твариною

Всякий яструб є птицею

Виключення - ромбоподібне множинне спадкоємство

Приведення типів вниз за ієрархією не завжди можливо

Не всякий ссавець - собака, але деякі ссавці можуть бути собаками

У C++ для такого приведення типів використовується оператор dynamic_cast

Приведення типа між незв'язаними класами ієрархії недопустимо

Собаки не є птицями

Кішка - не яструб і не собакаЯструб - не ссавець

Оператор

dynamic_cast

Оператор приведення типа dynamic_cast дозволяє виконати безпечне приведення заслання або покажчика на одного типа даних до іншого

Перевірка допустимості приведення типа здійснюється під час виконання програми

При неможливості приведення типа буде повернений нульовий покажчик (при приведенні типа покажчика) або згенерувало виключення типа std::bad_cast (при приведенні типа заслання)

Для здійснення перевірок часу виконання використовується інформація про типів (RTTI - Run- Time Type Information)

RTTI вимагає, аби в класі був хоч би один віртуальний метод (хоч би деструкор)

class CAnimal

{

public:

virtual ~CAnimal()

{}

};

class CBird

: public CAnimal

{};

class CEagle

: public CBird {};

class CMammal

: public CAnimal

{};

class CDog

: public CMammal

{};

class CCat

: public CMammal {};

void PrintAnimalType(CAnimal const * pAnimal)

{

if (dynamic_cast<CDog const*>(pAnimal) != NULL) std::cout << "dog\n";

else if (dynamic_cast<CCat const*>(pAnimal) != NULL) std::cout << "cat\n";

else if (dynamic_cast<CEagle const*>(pAnimal) != NULL) std::cout << "eagle\n";

else if (dynamic_cast<CMammal const*>(pAnimal) !=

NULL)

std::cout << "some unknown type of mammals\n"; else if (dynamic_cast<CBird const*>(pAnimal) != NULL)

std::cout << "some unknown type birds\n"; else

std::cout << "some unknown type of animals\n";

}

int main(int argc, char* argv[])

{

CDog dog; PrintAnimalType(&dog);

CAnimal * pAnimal = new CCat();

PrintAnimalType(pAnimal); delete pAnimal;

return 0;

}

CMammal const& MakeMammal(CAnimal const & animal)

{

return dynamic_cast<CMammal const&>(animal);

}

int main(int argc, char* argv[])

{

CDog dog;

CMammal const& dogAsMammal = MakeMammal(dog);

CCat cat;

// неявное приведение типов вверх по иерархии Cat -> Animal

CAnimal const& catAsAnimal = cat;

CMammal const& animalAsMammal = MakeMammal(catAsAnimal);

CEagle eagle; try

{

CMammal const& eagleAsMammal = MakeMammal(eagle);

}

catch(std::bad_cast const& error)

{

std::cout << error.what() << "\n";

}

return 0;

}

Не зловживайте

використанням dynamic_cast

Скрізь, де це можна, слід обходитися без використання даного оператора, віддаючи перевагу віртуальним (або чисто віртуальним функціям)

Інакше при додаванні нового класу в ієрархію може знадобитися провести ревізію всієї коди, що використовує dynamic_cast

При використанні віртуальних функцій нічого особливого робити не треба

class CAnimal

{

public:

virtual std::string GetType()const = 0; virtual ~CAnimal(){}

};

//птицы и млекопитающие – абстрактные понятия

//поэтому в них реализовывать GetType() нет

смысла

class CBird : public CAnimal{}; class CMammal : public CAnimal{};

class CEagle : public CBird

 

{

class CCat : public CMammal

public:

{

virtual std::string GetType()const

public:

{return "eagle";}

virtual std::string GetType()const

};

{return "cat";}

class CDog : public CMammal

};

 

{

void PrintAnimalType(CAnimal const &

public:

animal)

virtual std::string GetType()const

{

{return "dog";}

std::cout << animal.GetType() << "\n";

};

}