Hi, let's say I have a class that uses a rectangle's area, but the user cannot set the area as a setter, it needs to be calculated internally from a height and width setter.
As a general best practice, which one of the options below would be best to use (or any other approach I did not think of?):
1. a single set function for the height and width, and the area is the only private fct
1 2 3 4 5 6 7 8
class rect {
private:
_area;
public:
void setDimensions(int h, int w) {
_area = w*h;
}
}
2. two set functions for the height and width, and the area is constantly calculated every time it needs to be used. (wastes cpu, but the set fcts seem cleaner, and there is no redundant private member)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class rect {
private:
_w;
_h;
public:
void setHeight(int h) {
_h = h;
}
void setWidth(int w) {
_w = w;
}
int calculateArea() {
return _w*_h
}
}
3. two set functions for the height and width, and the area saved as a 3rd private member. (creates a redundant private member, but at least the calculations are only done once during set fcts)
Firstly, objects don't have setters/getters, they have methods that match operations you'd do on the object. I think that nonsense started with visual basic, in any event, if you find yourself thinking in these terms, stop.
As for what to do about calculated values, it depends on how costly the operation is. If you calculate an area once, then the object can do the calculation in the method. If you call it lots of times, you may want to cache it in a member.
As rectangle is using exceptions, wouldn't main() have a try/catch clause for invalid _argument?
@jcsb1944. IMO it depends upon the usage. If area() is called a lot after values have been set, then it may make sense to maintain a calculated value. Otherwise for the constructor/setter I'd go with JLBorges as above. For getter, I'd overload height() and width(). Note that with this you can't create an object with a default constructor - the constructor must be supplied values. If you need a default constructor, then you need to decide what values should be used for height/width (0?).
> As rectangle is using exceptions, wouldn't main() have a try/catch clause for invalid _argument?
In this case, we know that we are passing values which are known at compile time;
we know that an exception would never be thrown.
> If area() is called a lot after values have been set, then it may make sense to maintain a calculated value.
Multiplying two scalars and returning the result in an inline function is a trivial operation; it hardly takes any time. The memory overhead of caching is probably just not worth it in this particular case.