2014-03-28 51 views
4

我有一個基類,我聲明瞭幾個多態的子類。一些基類的函數是純虛擬的,而其他的則由子類直接使用。在基類中混合虛擬和非虛擬函數是不好的編程習慣嗎?

(這是所有C++)

因此,例如:

class Base 
{ 
protected: 
    float my_float; 
public: 

    virtual void Function() = 0; 

    void SetFloat(float value){ my_float = value} 

}

class subclass : public Base 
{ 

    void Function(){ std::cout<<"Hello, world!"<<std::endl; } 
} 

class subclass2 : public Base 
{ 

    void Function(){ std::cout<<"Hello, mars!"<<std::endl; } 
} 

因此,大家可以看到,子類將依賴於在基類函數設置「my_float」,但對於其他函數將是多態的。

所以我想知道這是否是好的做法。如果你有一個抽象基類,你應該完全抽象還是可以做這種混合方法?

+2

這聽起來很正常。我每天都用它們。 –

+0

你可以做到這一點。沒有什麼不好的編程,我可以在這裏感覺。這就是爲什麼純粹的虛擬功能。 – Abhineet

回答

5

這是一種常見的做法。事實上,一些着名的設計模式依賴於此,例如Template Method Pattern。簡而言之,這允許您指定通過類層次結構描述的行爲的某些方面爲不變,同時讓該行爲的其他方面根據您在給定點引用的特定類型的實例而有所不同。

不管它是不是一個好東西取決於你的確切用例:在你所有的基類中共享float成員數據存儲的實現是否合理?由於派生類不以任何方式依賴於my_float,所以這對於您發佈的示例有點難以回答,但有很多情況下這是合理的,並且是劃分類層次結構職責的好方法。

即使在跨類實現共享細節的情況下,您還有其他幾種選擇,例如使用合成來共享功能。通過基礎類共享功能通常可以減少冗餘,而不是通過組合共享此功能,因爲它允許您共享實現和接口。爲了說明這一點,你的解決方案比這種替代使用成分較少的重複代碼:

class DataStorage { 
private: 
    float data_; 
public: 
    DataStorage() 
    : data_(0.f) { 
    } 

    void setFloat(float data) { 
    data_ = data; 
    } 
}; 

class NotASubclass1 { 
private: 
    DataStorage data_; 
public: 
    void SetFloat(float value){ data_.setFloat(value); } 
    ... 
} 

class NotASubclass2 { 
private: 
    DataStorage data_; 
public: 
    void SetFloat(float value){ data_.setFloat(value); } 
    ... 
} 
+0

謝謝!說得通 – user1855952

2

能夠有一些功能非虛有一定的好處,許多密切相關:

  • 可以修改其中,通過Base*/Base&知道調用將使用您的修改後的代碼,無論什麼實際派生類型的Base*

    • 例如,你可以收集所有Base*/&的性能測量,無論其衍生的

    • 非虛擬接口(NVI)的方法的目的是爲「兩全其美」 - 非虛函數調用非公開虛擬功能,讓你在一個地方攔截通過在Base一個Base*/&電話以及定製靈活性

  • 調用非虛函數將可能會更快 - 如果行內,高達約一個數量級快速的瑣碎的功能,如獲取/設置爲幾個字節的字段

  • 可以確保用於從Base衍生,選擇性地封裝一些私人數據的所有對象不變量和影響它的功能(該final關鍵字引入在C++ 11允許這樣做進一步向下的層級)

  • Base類艾滋病的理解和推理類的行爲「已確定」數據/功能性和保理在令人沮喪的靈活性和不可預見的再利用的成本,使更多的簡潔的代碼的整體,但不一定 - 調味

相關問題