Imagine I have a class used to represent some trivial numerical data, like a vector. I want this class to be immutable in terms of its members, but still support correct copy-assignment behaviour.
This is what the shell of this class might look like:
class Vector {
public:
Vector(float _x, float _y);
private:
const float x;
const float y;
};
I would like to be able to assign a new value to a vector member within (for example) a class. An on-screen entity with a position, perhaps, represented using a non-const member of type Vector
.
This 'entity' must be mutable itself (perhaps supporting movement), e.g. the internal Vector
member used to store its position must change. Rather than modifying this member directly, I would rather replace it with an entirely new Vector
instance, initialised with the modified values.
In a language such as C#, I would simply compute the new values for X and Y based on the current Vector
instance, and assign a new Vector object initialised with these values to the member, discarding the previous value and letting the GC do the rest.
// Inside some class (C#/Java type)...
Vector position;
...
// Example function:
void Move(float _dX, float _dY) {
this.position = new Vector(_dX + position.X, _dY + position.Y);
}
This is where my limited ability with C++ comes into play, because I am unsure of how to implement operator=
in such a way that instances of this immutable type contained in dynamic memory do not simply 'disappear' and cause a leak.
So, I suppose, what I am asking is this:
Vector& operator=(const Vector& _rhs);
...
// In implementation file...
Vector& Vector::operator=(const Vector& _rhs) {
// WHAT ON EARTH GOES IN HERE?!?!?
}
The Vector
case is something I invented to get my point across, I can think of many sorts of types that should be immutable at the member level.
Am I wasting my time attempting to model immutable types?
Is there a better solution?
When you type
Vector position;
in a class definition, you define an instance of a Vector
class that will stay here forever. If that one is immutable, you're screwed.
In C#/Java, there is no way to do this. Instead you define references.
If you want to do the same thing in C++, you need pointers or auto_pointers
Vector* position;
That way, you can change the instance to which position
is pointing.
You shouldn't define the assignment operator of a immutable class. If you really need to, maybe you should make Vector
mutable, and use const Vector
when you need an immutable Vector
. You will just need to add const
qualifiers to method that are allowed with a const Vector
.
eg:
class Vector {
private:
float x;
float y;
public:
// allowed for const Vector
// because of the const before the '{'
float norm() const {
return hypot(x,y);
}
Vector& operator=(const Vector& o) {
x=o.x;
y=o.y;
return *this;
}
};