Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_ Лекция №09 - Композиция объектов.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
754.21 Кб
Скачать

Разрываемая ссылочная композиция

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

Ниже приведен пример класса, моделирующего вертолетную площадку (HelicopterPad). Площадка может принимать только один приземлившийся вертолет (Helicopter). Объект-вертолет может приземляться на площадку через вызов метода land, а затем покидать ее после вызова unland. Площадка должна проверять, что на ней может быть приземлен единственный вертолет, и что взлет возможен только, если вертолет до этого приземлился.

При этом уничтожение вертолета никогда не является задачей вертолетной площадки. В данном случае пропадает необходимость в наличии у класса-площадки собственного деструктора, поскольку никаких действий не требуется.

helicopterpad.hpp

#ifndef _HELICOPTERPAD_HPP_

#define _HELICOPTERPAD_HPP_

//************************************************************************

#include "point3d.hpp"

//************************************************************************

// Форвардное объявление класса-вертолета.

// Его содержимое не требуется для объявления класса-площадки.

class Helicopter;

//************************************************************************

// Класс-площадка

class HelicopterPad

{

/*-----------------------------------------------------------------*/

public:

/*-----------------------------------------------------------------*/

// Конструктор — задает координату местоположения, но не задает вертолета

HelicopterPad ( Point3D _location );

// Запрещенные конструктор копий и оператор присвоения

HelicopterPad ( const HelicopterPad & ) = delete;

HelicopterPad & operator = ( const HelicopterPad & ) = delete;

// Метод доступа к местоположению площадки

Point3D getLocation () const;

// Метод подтверждения приземления вертолета

bool hasLanded () const;

// Метод доступа к возможно приземлившемуся вертолету

Helicopter * getLanded () const;

// Метод регистрации приземления вертолета

void land ( Helicopter & _helicopter );

// Метод регистрации взлета вертолета

void unland ();

/*-----------------------------------------------------------------*/

private:

/*-----------------------------------------------------------------*/

// Координаты местоположения площадки.

// В отличие от вертолета, координаты площадки не могут изменяться

const Point3D m_location;

// Необязательная связь с приземлившимся объектом-вертолетом

Helicopter * m_pLanded;

/*-----------------------------------------------------------------*/

};

//************************************************************************

// Реализация метода доступа к местоположению площадки

inline Point3D

HelicopterPad::getLocation () const

{

return m_location;

}

//************************************************************************

// Реализация метода подтверждения приземления вертолета

inline bool HelicopterPad::hasLanded () const

{

// Если вертолет приземлился, значение указателя будет отлично от nullptr

return m_pLanded != nullptr;

}

//************************************************************************

// Реализация метода доступа к возможно приземлившемуся вертолету

inline Helicopter *

HelicopterPad::getLanded () const

{

// Даже если вертолет не приземлился, все корректно — метод вернет nullptr

return m_pLanded;

}

//************************************************************************

#endif // _HELICOPTERPAD_HPP_

helicopterpad.cpp

#include "helicopterpad.hpp"

#include "helicopter.hpp"

#include "point3d.hpp"

#include <stdexcept>

//************************************************************************

// Реализация конструктора

HelicopterPad::HelicopterPad ( Point3D _location )

: m_location( _location ),

m_pLanded( nullptr ) // Изначально вертолет не приземлялся

{

}

//************************************************************************

// Реализация метода регистрации приземления вертолета

void HelicopterPad::land ( Helicopter & _helicopter )

{

// Убеждаемся, что другой вертолет не приземлялся

if ( m_pLanded )

throw std::logic_error( "Something has already landed on this pad" );

// Подводим вертолет к точке приземления

_helicopter.moveTo( getLocation() );

// Создаем связь между объектами — // запоминаем адрес объекта-вертолета в объекте-площадке

m_pLanded = & _helicopter;

}

//************************************************************************

// Реализация метода регистрации взлета вертолета

void HelicopterPad::unland ()

{

// Убеждаемся, что вертолет приземлялся

if ( ! m_pLanded )

throw std::logic_error( "No helicopter is currently landed" );

// Вертолет должен взлететь на 7м строго над площадкой

m_pLanded->moveTo(

Point3D(

getLocation().getX(),

getLocation().getY(),

getLocation().getZ() + 7.0

)

);

// Разрываем связь между объектами обнулением указателя

m_pLanded = nullptr;

}

//************************************************************************

test_pads.cpp

#include "helicopterpad.hpp"

#include "helicopter.hpp"

#include <cassert>

int main ()

{

// Создаем вертолетную площадку

HelicopterPad * pHeliPad = new HelicopterPad( Point3D( 1.0, 2.0, 0.0 ) );

// Изначально на площадке никто не приземлен

assert( ! pHeliPad->hasLanded() );

// Создаем вертолет

Helicopter * pHelicopter = new Helicopter( 1 );

// Приземляем вертолет на площадке

pHeliPad->land( * pHelicopter );

// Убеждаемся, что на площадке находится наш вертолет

assert( pHeliPad->hasLanded() && pHeliPad->getLanded() == pHelicopter );

// Убеждаемся, что текущее местоположение вертолета совпадает с местом площадки

Point3D location = pHelicopter->getCurrentPosition();

assert( location == pHeliPad->getLocation() );

// Взлетаем

pHeliPad->unland();

// На площадке не должно остаться вертолета

assert( ! pHeliPad->hasLanded() );

// Координаты X/Y вертолета должны совпадать с координатами площадки,

// однако координата Z должна отличаться (вертолет взлетает идеально вверх)

Point3D newLocation = pHelicopter->getCurrentPosition();

assert( newLocation.getX() == location.getX() &&

newLocation.getY() == location.getY() &&

newLocation.getZ() > location.getZ() );

// Уничтожаем площадку и вертолет

delete pHeliPad;

delete pHelicopter;

}