假設一個類表示一個3x3矩陣,並在其構造函數中使用9個任意數字,並讓該類有一個inverse()方法。因爲不是所有的矩陣都是可逆的,所以inverse()方法返回一個可選值(或可空指針),它必須在運行時由調用者檢查。然而,某些3×3矩陣總是可逆的,只要矩陣中的值遵循一定的規則,例如, 3D旋轉矩陣。我們可以用一個子類來編碼,這個子類不允許直接構造,而是通過使用一些特殊規則構造的,例如圍繞笛卡爾座標軸的旋轉角度。設計模式是否存在用於對子類的數據執行規則?
最終的結果是這個層次結構,它應該允許層次結構的客戶端在使用子類時具有編譯時安全性(例如,客戶端保證object.rotate(rotationMatrix.inverse())將始終有效,假設rotationMatrix是類型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);
}
}
所以分解原來的問題:
- 是有比上述以實現這一目標功能之外的其他模式?
- 如果沒有其他模式存在,C++有沒有辦法阻止(或者至少明確地向未來的開發者發出信號)子類不能引入新的狀態或構造函數以避免投射問題(例如切片等)?
不是設計模式,但你可能也拋出一個異常時,'逆()'在具有0行列式的矩陣上被調用。如果矩陣是用常量值構造的(而不是在調用'cos'和'sin'的旋轉矩陣中的情況),則可以在編譯時計算並測試行列式 – wasthishelpful
您的Matrix是不可變的結構嗎?如果沒有,那麼你的代碼會有問題... – Holt
'optional'(在C++ 17中'std ::',否則'boost ::')將是'unique_ptr'的一個很好的替代品。 – Jarod42