Let's say a class represents a 3x3 matrix and takes 9 arbitrary numbers in its constructor and let that class have an inverse() method. Since NOT all matrices are invertible, the inverse() method returns an optional value (or a nullable pointer) which must be checked by callers at runtime.
However, certain 3x3 matrices are ALWAYS invertible, as long as the values in the matrix follow certain rules, e.g. 3D rotation matrices. We can codify that with a subclass, which does NOT allow direct construction but is constructed by using some special rules, e.g the rotation angle around a Cartesian axis.
The end result is this hierarchy, which should allow a client of the hierarchy to have compile time safety when using the subclass (e.g. a client is guaranteed that object.rotate(rotationMatrix.inverse()) will always work, assuming rotationMatrix is of type RotationMatrix):
class Matrix {
public:
Matrix(double e_0_0, double e_0_1, double e_0_2,
double e_1_0, double e_1_1, double e_1_2,
double e_2_0, double e_2_1, double e_2_2) {
...
}
std::unique_ptr<Matrix3x3> inverse() const {
if (isInvertible) {
return std::unique_ptr(new Matrix3x3(...));
}
return std::unique_ptr();
}
}
class RotationMatrix : public Matrix3x3 {
public:
static RotationMatrix getRotationAroundX(double angle) {
return asRotationMatrix(Matrix(1, 0, 0,
0, cos(angle), -sin(angle),
0, sin(angle), cos(angle)));
}
RotationMatrix inverse() const {
return asRotationMatrix(*Matrix::inverse().get()));
}
private:
static const RotationMatrix3D& asRotationMatrix(const Matrix3x3& matrix) {
return static_cast<const RotationMatrix3D&>(matrix);
}
}
So to break down the original question:
- is there a pattern other than the one described above to achive this functionality?
- if no other pattern exists, is there a way in C++ to prevent (or at least clearly signal to future developers) that the subclass MUST NOT introduce new state or constructors in order to avoid casting issues (e.g. slicing, etc)?