I have a question about the much-commented-about C++ reference getter-setter in C++. This is the base code:
class Foo
{
X x_;
public:
X & x() { return x_; }
const X & x() const { return x_; }
}
My issue with this is: what if I need to check the value when I set it? Let's imagine that I'm setting the latitude of a coordinate. If I were writing a setLat
method, it would look like this:
void MyClass::setLat(double lat)
{
if (lat < -90 || lat > 90)
{
throw std::range_error("The latitude must be between -90 and 90.");
}
_lat = lat;
}
Can I do something similar with:
double & MyClass::lat()
{
return _lat;
}
When I saw the code at the top of this question as the answer of another StackOverflow question, I thought, "Cool." But then, I ended up realizing what people here are saying: it breaks encapsulation. This member might just as well be public.
Since I don't use C++ that often, I wasn't too sure, thought.
The answer given by @ted-lyngmo did however make a lot of sense. I think that just having a regluar getter and a setter might in the end be the best. But I thought it might be possible to mimic the property ability of C# and Python in recent versions of C++. It looks like it is. Now: is it a good idea to do it? The question still seems open.
One option is to make a user-defined type of latitude and put all validations in that:
class Latitude {
public:
Latitude() = default;
explicit Latitude(double lat) : m_latitude(lat) {
if (m_latitude < -90 || m_latitude > 90)
throw std::range_error("The latitude must be between -90 and 90.");
}
explicit operator double() const { return m_latitude; }
private:
double m_latitude = 0.;
};
That way you could keep the class containing a latitude clean:
class MyClass {
public:
void setLat(Latitude lat) {
_lat = lat;
}
private:
Latitude _lat;
};
or
class MyClass {
public:
Latitude& latitude() {
return _lat;
}
private:
Latitude _lat;
};