- •Ооп: Лекция 9. Композиция объектов.
- •Композиция объектов
- •Простейшая композиция по значению
- •Множественная композиция по значению
- •Ссылочная композиция — логическое объединение
- •Композиция с разрываемой связью
- •Разрываемая ссылочная композиция
- •Недетерминированная множественность композиции
- •Множественная композиция объектов-сущностей
- •Полные примеры из лекции
Простейшая композиция по значению
Ниже представлен класс для точки в 3-х мерном пространстве:
point3d.hpp
#ifndef _POINT3D_HPP_
#define _POINT3D_HPP_
//************************************************************************
class Point3D
{
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
// Конструктор по умолчанию – задает начало координат
Point3D ();
// Конструктор с аргументами — задает конкретные значения координат
Point3D ( double _x, double _y, double _z );
// Методы доступа к координатам
double getX () const;
double getY () const;
double getZ () const;
// Метод вычисления расстояния до другой точки
double distanceTo ( Point3D _p ) const;
// Перегруженные операторы сравнения на равенство и неравенство
bool operator == ( Point3D _p ) const;
bool operator != ( Point3D _p ) const;
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// Координаты точки по каждой из осей
double m_x, m_y, m_z;
};
//************************************************************************
// Метод доступа к координате по оси абсцисс
inline double Point3D::getX () const
{
return m_x;
}
//************************************************************************
// Метод доступа к координате по оси ординат
inline double Point3D::getY () const
{
return m_y;
}
//************************************************************************
// Метод доступа к координате по оси аппликат
inline double Point3D::getZ () const
{
return m_z;
}
//************************************************************************
#endif // _POINT3D_HPP
point3d.cpp
#include "point3d.hpp"
#include <cmath>
//************************************************************************
// Реализация конструктора по умолчанию
Point3D::Point3D ()
: m_x( 0.0 ), m_y( 0.0 ), m_z( 0.0 )
{
}
//************************************************************************
// Реализация конструктора с аргументами
Point3D::Point3D ( double _x, double _y, double _z )
: m_x( _x ), m_y( _y ), m_z( _z )
{
}
//************************************************************************
// Реализация метода вычисления расстояния до другой дочки
double Point3D::distanceTo ( Point3D _p ) const
{
double xDiff = _p.getX() - getX();
double yDiff = _p.getY() - getY();
double zDiff = _p.getZ() - getZ();
return sqrt( xDiff * xDiff + yDiff * yDiff + zDiff * zDiff );
}
//************************************************************************
// Реализация оператора сравнения на равенство
bool Point3D::operator == ( Point3D _p ) const
{
return getX() == _p.getX() &&
getY() == _p.getY() &&
getZ() == _p.getZ();
}
//************************************************************************
// Реализация оператора сравнения на равенство
bool Point3D::operator != ( Point3D _p ) const
{
return !( * this == _p );
}
//************************************************************************
Класс для окружности использует реализованный выше класс для точки для дочернего объекта, означающего координаты центра. Точка хранится в окружности по значению и не может быть отделена от окружности:
circle.hpp
#ifndef _CIRCLE_HPP_
#define _CIRCLE_HPP_
//************************************************************************
#include "point3d.hpp"
//************************************************************************
class Circle
{
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
// Конструктор
Circle ( Point3D _center, double _radius );
// Метод доступа к координатам центра
Point3D getCenter () const;
// Метод доступа к радиусу
double getRadius () const;
// Метод вычисления длины окружности
double getPerimeter () const;
// Метод вычисления площади окружности
double getArea () const;
// Метод вычисления координаты точки на окружности под определенным углом
Point3D getPointOn ( double _angle ) const;
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// Центр окружности — дочерний объект класса Point3D
Point3D m_center;
// Радиус окружности
double m_radius;
/*-----------------------------------------------------------------*/
};
//************************************************************************
// Реализация метода доступа к координатам центра
inline Point3D
Circle::getCenter () const
{
return m_center;
}
//************************************************************************
// Реализация метода доступа к радиусу
inline double
Circle::getRadius () const
{
return m_radius;
}
//************************************************************************
#endif // _CIRCLE_HPP_
circle.cpp
#include "circle.hpp"
#define _USE_MATH_DEFINES // <- необходимо для работы с константой M_PI
#include <cmath>
#include <stdexcept>
//************************************************************************
// Реализация конструктора
Circle::Circle ( Point3D _center, double _radius )
: m_center( _center ) // <= вызов конструктора копий Point3D
, m_radius( _radius )
{
// Инвариант: радиус должен быть положительным
if ( m_radius <= 0.0 )
throw std::logic_error( "Circle radius must be positive" );
}
//************************************************************************
// Реализация метода вычисления длины окружности
double Circle::getPerimeter () const
{
return 2.0 * M_PI * m_radius;
}
//************************************************************************
// Реализация метода вычисления площади окружности
double Circle::getArea () const
{
return M_PI * m_radius * m_radius;
}
//************************************************************************
// Реализация метода вычисления координат точки на окружности под заданным углом
Point3D Circle::getPointOn ( double _angle ) const
{
// Вычисляем длины катетов по гипотенузе (радиусу) и углу
double xOffset = m_radius * cos( _angle );
double yOffset = m_radius * sin( _angle );
// Создаем новый объект-точку
return Point3D( m_center.getX() + xOffset,
m_center.getY() + yOffset,
m_center.getZ()
);
}
//************************************************************************
В свою очередь, класс-цилиндр использует в качестве дочернего объекта окружности для моделирования основания. Аналогично предыдущему случаю, дочерний объект-окружность хранится в объекте-цилиндре по значению. А значит внутри объекта-цилиндра есть и объект-точка, представляющая собой центр окружности-основания:
cylinder.hpp
#ifndef _CYLINDER_HPP_
#define _CYLINDER_HPP_
//************************************************************************
#include "circle.hpp"
//************************************************************************
class Cylinder
{
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
// Конструктор. Передаем основание по ссылке.
// Передача основания по значению также допустима.
Cylinder ( Circle _base, double _height );
// Метод доступа к объекту-основанию
Circle getBase () const;
// Метод доступа к высоте цилиндра
double getHeight () const;
// Метод вычисления объема цилиндра
double getVolume () const;
// Метод вычисления площади поверхности сторон
double getSideSurfaceArea () const;
// Метод вычисления всей площади поверхности
double getFullSurfaceArea () const;
// Метод вычисления координат точки на поверхности под определенным углом
// и на заданной высоте
Point3D getPointOnSurface ( double _angle, double _height ) const;
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// Основание цилиндра — дочерний объект класса Circle
Circle m_base;
// Высота цилиндра
double m_height;
/*-----------------------------------------------------------------*/
};
//************************************************************************
// Реализация метода доступа к объекту-основания
inline Circle
Cylinder::getBase () const
{
return m_base;
}
//************************************************************************
// Реализация метода доступа к высоте
inline double
Cylinder::getHeight () const
{
return m_height;
}
//************************************************************************
#endif // _CYLINDER_HPP_
cylinder.cpp
//************************************************************************
#include "cylinder.hpp"
#include <cmath>
#include <stdexcept>
//************************************************************************
// Реализация конструктора
Cylinder::Cylinder ( const Circle & _base, double _height )
: m_base( _base ) // <= вызов конструктора копий класса Circle
, m_height( _height )
{
// Инвариант: высота должна быть положительной
if ( m_height <= 0.0 )
throw std::logic_error( "Cylinder height must be positive" );
}
//************************************************************************
// Реализация метода вычисления объема
double Cylinder::getVolume () const
{
return m_base.getArea() * m_height;
}
//************************************************************************
// Реализация метода вычисления площади поверхности сторон
double Cylinder::getSideSurfaceArea () const
{
return m_base.getPerimeter() * m_height;
}
//************************************************************************
// Реализация метода вычисления площади полной поверхности
double Cylinder::getFullSurfaceArea () const
{
return getSideSurfaceArea() + 2.0 * m_base.getArea();
}
//************************************************************************
// Реализация метода вычисления координат точки на поверхности
Point3D Cylinder::getPointOnSurface ( double _angle, double _height ) const
{
// Вычисляем координаты точки на основании
Point3D circlePoint = m_base.getPointOn( _angle );
// Создаем новую точку с учетом высоты
return Point3D( circlePoint.getX(), circlePoint.getY(), circlePoint.getZ() + _height );
}
//************************************************************************
