Section 17.6 Implementing Composition
To build our Circle using composition, we need to have a full implementation of Point. We will rely on the version of the Point code shown below. Donβt worry about trying to memorize it all, most of the code should already be familiar to you. And if you ever need to double check how some part of it works, you can double check the details here.
module; //start global module fragment
#include <format>
#include <string>
#include <cmath> // for sqrt
export module Point;
/**
* @brief Represents a point in a 2D Cartesian coordinate system.
*/
export class Point {
public:
/**
* @brief Constructs a Point with the specified coordinates.
* @param x The x-coordinate of the point.
* @param y The y-coordinate of the point.
*/
Point(double x, double y);
/**
* @brief Constructs a Point at the origin (0, 0).
*/
Point();
/**
* @brief Gets the x-coordinate of the point.
* @return The x-coordinate.
*/
double getX() const;
/**
* @brief Gets the y-coordinate of the point.
* @return The y-coordinate.
*/
double getY() const;
/**
* @brief Sets the x-coordinate of the point.
* @param x The new x-coordinate.
*/
void setX(double x);
/**
* @brief Sets the y-coordinate of the point.
* @param y The new y-coordinate.
*/
void setY(double y);
/**
* @brief Shifts the point by the specified offsets.
* @param dx The offset to add to the x-coordinate.
* @param dy The offset to add to the y-coordinate.
*/
void shift(double dx, double dy);
/**
* @brief Converts the point to a string representation.
* @return A string representing the point in the format "(x, y)".
*/
std::string toString() const;
/**
* @brief Calculates the distance to another point.
* @param other The other point.
* @return The Euclidean distance to the other point.
*/
double distanceTo(const Point& other) const;
private:
double m_x;
double m_y;
};
Point::Point(double x, double y) {
m_x = x;
m_y = y;
}
Point::Point() {
m_x = 0;
m_y = 0;
}
double Point::getX() const {
return m_x;
}
double Point::getY() const {
return m_y;
}
void Point::setX(double x) {
m_x = x;
}
void Point::setY(double y) {
m_y = y;
}
void Point::shift(double dx, double dy) {
setX(getX() + dx);
setY(getY() + dy);
}
std::string Point::toString() const {
return std::format("({}, {})", getX(), getY());
}
double Point::distanceTo(const Point& other) const {
double xdiff = other.m_x - m_x;
double ydiff = other.m_y - m_y;
double distance = sqrt(xdiff * xdiff + ydiff * ydiff);
return distance;
}
The class declaration for Point will need to be available to the Circle class when we define the Point class. Although we could do that by placing both classes in the same file, the standard way to structure our code would be to either:
-
If using modules,
import Point;
into the file where we implementCircle
. -
If using traditional .h/.cpp files,
#include "Point.h"
into the file where we implementCircle
.
We will be using the module approach in this chapter, although a .h/.cpp version is available at the end of the chapter. We will start by implementing Circle in the same file as our main function and separate it out later.
Here is a very first pass at the Circle class. For now, we will just provide a constructor:
Some key ideas to note:
-
Line 3: We import the Point module so we can use it in our Circle class.
-
Line 15-16: The member variables are one double and one Point.
-
Line 11: The constructor takes an x and a y location. But the Circle does not store these directly. Instead, it makes an anonymous Point to store those values and copies that point into
m_center
.
We donβt have any getters or other functions we can use to see if the code works. But a memory diagram at the end of main would look like the image below.
In this model, the x and y coordinates are the Pointβs responsibility. The
m_center
is used to store the values m_x
and m_y
and, as we will see soon, any time the Circle needs to work with the coordinates, it will rely on the m_center
to access them.
You have attempted of activities on this page.