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

Множественная композиция по значению

Кратность дочерних объектов может быть множественной. В таком случае используются массивы дочерних объектов. Если количество объектов заранее известно, массив фиксированного размера размещается непосредственно в родительском объекте. Чаще количество объектов заранее неизвестно и определяется во время выполнения. При этом количество передается в конструкторе, который выделяет динамический блок памяти для хранения желаемого количества дочерних объектов, а в родительском объекте сохраняется указатель на начало блока. Разумеется, родительский объект становится ответственным за уничтожение выделенного блока памяти, что следует в явном виде реализовать в деструкторе. Таким действиям в родительском классе обычно сопутствуют определения конструкторов копий и перемещения, а также соответствующих операторов присвоения и перемещения.

Ниже представлен класс для многоугольника, состоящий из множества точек (в показанном примере, из 4 точек конкретно):

polygon.hpp

#ifndef _POLYGON_HPP_

#define _POLYGON_HPP_

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

#include "point3d.hpp"

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

class Polygon

{

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

public:

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

// Конструктор — принимает количество точек

Polygon ( int _nPoints );

// Конструктор копий

Polygon ( const Polygon & _p );

// Конструктор перемещения

Polygon ( Polygon && _p );

// Деструктор

~Polygon ();

// Оператор присвоения

Polygon & operator = ( const Polygon & _p );

// Оператор перемещения

Polygon & operator = ( Polygon && _p );

// Метод доступа к количеству точек

int getNPoints () const;

// Методы доступа к точке по индексу

const Point3D & getPoint ( int index ) const;

Point3D & getPoint ( int _index );

// Метод вычисления длины сторон многоугольника

double getPerimeter () const;

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

private:

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

// Начала блока хранения точек

Point3D * m_points;

// Количество точек

int m_nPoints;

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

};

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

// Реализация метода доступа к количеству точек

inline int Polygon::getNPoints () const

{

return m_nPoints;

}

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

#endif // _POLYGON_HPP_

polygon.cpp

#include "polygon.hpp"

#include <stdexcept>

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

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

Polygon::Polygon ( int _nPoints )

: m_nPoints( _nPoints ) // Запоминаем количество точек

{

// Проверяем инвариант - как минимум 3 точки! if ( _nPoints < 3 )

throw std::logic_error( "Expecting at least 3 points in polygon" );

// Выделяем блок для хранения точек и запоминаем адрес // его начала в объекте-многоугольнике

m_points = new Point3D[ m_nPoints ];

}

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

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

Polygon::Polygon ( const Polygon & _p )

{

// Извлекаем количество точек из объекта-оригинала

m_nPoints = _p.m_nPoints;

// Выделяем блок для хранения точек и // запоминаем адрес его начала в объекте-многоугольнике

m_points = new Point3D[ m_nPoints ];

// Копируем координаты точек

for ( int i = 0; i < m_nPoints; i++ )

m_points[ i ] = _p.m_points[ i ];

}

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

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

Polygon::Polygon ( Polygon && _p )

{

// Извлекаем количество точек из объекта-оригинала

m_nPoints = _p.m_nPoints;

// "Отбираем" у объекта-оригинала блок данных

m_points = _p.m_points;

_p.m_points = nullptr;

}

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

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

Polygon::~Polygon ()

{

// Освобождаем блок для хранения точек

delete[] m_points;

}

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

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

Polygon & Polygon::operator = ( Polygon const & _p )

{

// Защита от присвоения самому себе

if ( this == & _p )

return * this;

// Освобождаем предыдущий блок с точками

delete[] m_points;

// Извлекаем количество точек из объекта в правой части присвоения

m_nPoints = _p.m_nPoints;

// Выделяем блок для хранения точек и запоминаем адрес его начала // в объекте-многоугольнике

m_points = new Point3D[ m_nPoints ];

// Копируем координаты точек

for ( int i = 0; i < m_nPoints; i++ )

m_points[ i ] = _p.m_points[ i ];

// Возвращаем ссылку на себя

return * this;

}

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

// Реализация оператора перемещения

Polygon & Polygon::operator = ( Polygon && _p )

{

// Защита от перемещения в самого себя

if ( this == & _p )

return * this;

// Осуществляем обмен переменными

std::swap( m_nPoints, _p.m_nPoints );

std::swap( m_points, _p.m_points );

// Возвращаем ссылку на себя

return * this;

}

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

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

const Point3D & Polygon::getPoint ( int _index ) const

{

if ( _index >= 0 && _index < getNPoints() )

return m_points[ _index ];

else

throw std::logic_error( "Point index is out of range" );

}

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

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

Point3D & Polygon::getPoint ( int _index )

{

if ( _index >= 0 && _index < getNPoints() )

return m_points[ _index ];

else

throw std::logic_error( "Point index is out of range" );

}

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

// Реализация метода вычисления длины сторон многоугольника

double Polygon::getPerimeter () const

{

// Суммируем расстояния между соседними точками многоугольника

double total = 0.0;

for ( int i = 0; i < m_nPoints - 1; i++ )

total += m_points[ i ].distanceTo( m_points[ i + 1 ] );

return total;

}

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