We can use objects as parameters to functions in the same way we use structs. Just as with structs, we need to consider whether we want to pass the object by value or by reference. Passing by reference is usually the better choice, since it avoids copying the object. This is especially important for large objects, where copying can be expensive in terms of time and memory. And, if we donβt want to modify the object, we should pass it as a const reference. This way, we can be sure that the function wonβt change the object.
This somewhat cryptic message is complaining that using the member function getX() is not guaranteed to be safe on the Point that this function promises to not modify (const Point& p2). The compiler looks at that line and is not sure if it is safe to call getX(). For all it knows, that function is going to change p2! (Remember that compiler does not necessarily have all the code available as it compiles this file. It only works on one file at a time.)
How do we deal with this? Well, we could just stop using const. Then the compiler would not worry about taking a Point we promised to keep const and calling some member function that might modify the Point. But that means ignoring a power tool for avoiding bugs based on unintended changes made via references. So a better way to solve the issue is to tell the compiler which member functions are safe to use on const objects.
class Point {
public:
double getX() const {
return m_x;
}
double getY() const; // defined later
...
}; // end of point class
double Point::getY() const {
return m_y;
}
const becomes part of the prototype of the function. getX is now βThe getX function that is a part of Point, returns a double, and keeps the object constantβ. Anywhere we write the prototype, like on line 10 to define the getY that was declared on line 6, we must use the const.
Now, when we call getX() on a const Point, the compiler knows that it is safe to do so as the function was marked const. As it compiles the getX() function itself, does not try to modify any member variables. If it does, the compiler will flag that change as an error.
const is infectious in object-oriented code. Once we start using it, it becomes important to use it everywhere so the compiler knows what operations are safe.
So what do we mark const? Any functions that do not change the current object. In the version of Point below, that includes getX(), getY(), and toString(). We canβt mark the setters, shift() or the constructor as const as they all modify (or create) the object:
Note that it is still not OK to use non-const functions. If you add a line p1.setX(10) to the distanceBetween code, it will produce an error. You are now calling a function that is not known to be safe on a Point we promised to keep const.