Section 17.10 Returning Composed Objects
As we start implementing getters for our Circle, we might decide we want a
getCenter()
in addition to getX()
and getY()
. If a client of the class wants to know where a circle is, asking for the center Point is easier than asking for the x and y values separately. But this raises an important question: what should the getCenter()
return?
We could return a copy of the Point from the Circleβs
getCenter()
method:
Point Circle::getCenter() const {
return m_center;
}
Any time we return an object type like that, we are returning a copy of the center point. This means that doing
Point p2 = c1.getCenter()
would produce a brand new Point that just copied the data from c1βs center:
This is the easiest thing to do. And, in many ways the safest. By giving the client a copy of its center, the Circle does not need to worry about what happens to the Point.
Note 17.10.1.
We will generally use that easy approach. The rest of this section focuses on improvements that would only be worth making in a program that worked with lots of data or to solve complex design problems. Mastering these concepts should be a lower priority than mastering the rest of the chapter.
However, the easy approach is not always the best approach. Firstly, it involves copying the Point. This is not a big deal for a small class like Point that we only copy a few (or even a few hundred) times. But if we were to copy a large object, or make millions of copies of small ones, the expense would become something to be concerned about. Secondly, we might want to allow the client to use the Point we give them to change the center of the circle.
To avoid the copy, we can return a reference to the Point. This would look like:
Point& Circle::getCenter() {
return m_center;
}
Now, we are returning a reference to the actual
m_center
object. If the client stores the returned value as a reference (Point& p3 = c1.getCenter();
) it has a link to the Point object that is actually the center of c1:
In this case,
p3.setY(10)
would actually change the m_y
of the m_center
of c1
as p3
is just another name for c1.m_center
. Because the reference can be used to modify the Point (and thus the Circleβs data), this version of getCenter
is not (and can not be) const.
If the client wants, it could store the value into a plain Point variable with
Point p4 = c1.getCenter();
. In this case, we are taking the reference, and copying it into the new p4. The reference is then discarded. So we end up with a memory diagram that looks just like FigureΒ 17.10.1.
What if we want to return a reference to a Point but we donβt want the client to be able to modify it? We could do this by returning a
const
reference. This would look like:
const Point& Point::getCenter() const {
return m_center;
}
What a mouthful.
Circle::getCenter() const
is a const function (it will not allow changes to the Circle or its data). It returns (const Point &
) a reference to a Point that is constant.
The const on the return type says that the reference we return can not be used to make changes to the Point. To honor that requirement, client code would need to store the returned value into a const reference:
const Point& p5 = c1.getCenter();
. The memory diagram would look just like the normal reference version (FigureΒ 17.10.2), but p5 could only be used to access const members of the Point class like getX()
. We could not use it to do anything that would change the Point.
You have attempted of activities on this page.