2016-08-17 31 views
2

假設一個類表示一個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

不是設計模式,但你可能也拋出一個異常時,'逆()'在具有0行列式的矩陣上被調用。如果矩陣是用常量值構造的(而不是在調用'cos'和'sin'的旋轉矩陣中的情況),則可以在編譯時計算並測試行列式 – wasthishelpful

+0

您的Matrix是不可變的結構嗎?如果沒有,那麼你的代碼會有問題... – Holt

+0

'optional'(在C++ 17中'std ::',否則'boost ::')將是'unique_ptr'的一個很好的替代品。 – Jarod42

回答

0

這些約束應該通過接口強制執行,在這種情況下,通過構造函數和任何可能的mutators(setters)。這非常符合你描述的模式。

爲了防止將來的開發人員通過繼承混淆了類的內部,請通過聲明private來使相關數據成員(即您想保護的數據成員)無法訪問。

由於C++ 11,您還可以聲明您的類final,以便任何人都無法繼承它。

0

在C++中有沒有辦法阻止(或者至少明確地向未來的開發者發出信號)子類不能引入新的狀態?不幸的是,答案是否定的。在任何OO語言的所有層次使用,作爲一個一般規律:子類可以做它的父做的所有東西,並可以添加其他方法和attributs

,如果你有特殊的要求,你可以做的更好,是寫一份文件並在那裏明確說明。

3

在這裏,你打circle/ellipse problem

最好能有不同的類別和用途的組合物:

class RotationMatrix { 
public: 

    static RotationMatrix getRotationAroundX(double angle) { 
     return { Matrix(1,   0,   0, 
         0, cos(angle), -sin(angle), 
         0, sin(angle), cos(angle))}; 
    } 

    RotationMatrix inverse() const { 
     return {*Matrix::inverse().get()}); 
    } 

    const Matrix3x3& AsMatrix() const { return matrix; } 

private: 
    static RotationMatrix(const Matrix3x3& matrix) : matrix(matrix) {} 
    Matrix3x3 matrix; 
}; 
+0

對於這類東西,C++中'private'繼承是不是更好? – Holt

+1

@霍爾特:除非你需要(私人)繼承,否則我寧願組合。參見[私有繼承vs組合時何時使用](http://stackoverflow.com/questions/7209019/private-inheritance-vs-composition-when-to-use-which) – Jarod42

相關問題