Reputation: 7248
Will explain this with a simple example.
class Vector
{
float X;
float Y;
float _length;
float Length();
}
I only what to calculate Length and assign it to _length if X or Y changed. If none of them changed I just simply return _length.
Upvotes: 1
Views: 1268
Reputation: 15334
An alternative to maintaining guard flags or "invalid" values as suggested by Jeff would be to use nullable objects such as pointers, preferably smart pointers. This may be more appropriate when the cache is an object larger than a float
.
class Vector {
float X;
float Y;
mutable std::unique_ptr<float> length_;
public:
Vector() : X(0.0f), Y(0.0f) { }
Vector(float x, float y) : X(x), Y(y) { }
float x() const { return X; }
float y() const { return Y; }
float length() const {
if (!length_)
length_ = std::unique_ptr<float>(new float(sqrt(X*X + Y*Y)));
return *length_;
}
void setX(float x) { if (X != x) { length_.reset(); X = x; } }
void setY(float y) { if (Y != y) { length_.reset(); Y = y; } }
};
Upvotes: 0
Reputation: 3525
You'll need to include a guard flag (or "invalid" value) that you flag with X
/Y
modifications through:
class Vector {
public:
Vector(float x = 0.0, float y = 0.0)
: X{x}, Y{y}, Length{-1.0f}
{ }
float x() const { return X; }
float y() const { return Y; }
float length() const {
if (Length < 0.0f) {
Length = sqrt(X*X + Y*Y);
}
return Length;
}
void setX(float x) { if (X != x) { Length = -1.0f; } X = x; }
void setY(float y) { if (Y != y) { Length = -1.0f; } Y = y; }
private:
float X;
float Y;
mutable float Length;
};
The mutable
qualifier means those values are not part of the "logical" state of an object and can be modified even on a const
instance of Vector
(via const
member functions, naturally).
Upvotes: 5
Reputation: 2522
first thing that came to mind:
class Vector
{
public:
void setX(float x) {changed = true; X = x;}
void setY(float y) {changed = true; Y = y;}
float length()
{
if (changed)
// calculate
changed = false;
return _Length;
}
private:
floate X, Y, _Length;
bool changed;
};
edit: i hope now the formating works ...
Upvotes: 0
Reputation: 1263
Make x
and y
private and add two functions like
void setX(float x) {
this -> x = x;
handleLengthChange();
}
and
void setY(float y) {
this -> y = y;
handleLengthChange();
}
The function handleLengthChange
calculates the new length.
Every class that uses Vector
will now use the methods above to change x or y.
Since x and y are private, just add two functions to get the values of x and y.
Upvotes: 1
Reputation: 42929
Easy, calculate length on the fly from variables X
and Y
. This way you'll get always the right length, no matter if X
or Y
has changed or not.
float Vector::Length()const
{
return sqrt(X * X + Y * Y);
}
Upvotes: 0
Reputation: 75815
make X
and Y
accessible only through setters and getters. Have a boolean value that tells you if _length
is up to date. On X
and Y
setters invalidate _length
(via that boolean variable). When getting the length check if _length
if valid. If yes just return it. If not compute it, make it valid and return it.
Upvotes: 0
Reputation: 4463
make your float X, Y;
private and add a bool changed;
to your class as well.
changing X, Y will be done through setters functions that will also set the bool changed
to false.
whenever you call the function Length();
it checks for the bool changed
variable, if false then recalculate.
class Vector
{
float X;
float Y;
bool changed;
float _length;
void setX (float val) { // the same for Y
X = val;
changed = true;
}
float Length(){
if (changed)
//compute Length
changed = false;
return ComputedValue;
}
}
Upvotes: 0