2010-06-10 87 views
5

我有一個基類和幾個派生類。派生類使用一些常用數據,我可以將這些常用數據作爲基類的受保護成員嗎?我知道受保護的成員有時會打破封裝,所以我想知道是否有任何好的方法。基類中的通用受保護數據成員?

這裏是一個具體的例子:

class Base{ 
public: 
    virtual void foo() = 0; 
    void printData(); 
protected: 
    std::vector<std::string> mData; 
} 

class Dr1 : public Base{ 
public: 
    virtual void foo(); //could change mData 
} 

class Dr2 : public Base{ 
public: 
    virtual void foo(); //could change mData 
} 

如果我把MDATA到DR 1和DR作爲私有成員,那麼我就需要把它放在他們兩人,並在基地我不能有printData()因爲printData()需要訪問mData,除非我使printData()虛擬並且在Dr1和Dr2中具有相同的功能,這對我來說沒有多大意義。

有沒有更好的方法來處理這個問題,而不使用保護成員?謝謝。

回答

3

要考慮的一個設計是使mData專用,並向Base中添加受保護的方法,從而爲數據提供通用操作,然後Dr1和Dr2可以使用該方法。

但是有很多次將mData作爲受保護成員更有意義。最好的辦法很大程度上取決於班級的細節。

0

只要所有派生類都具有該成員是合理的,那麼將它放入基類中是很有意義的。

原因,我看不把它還有:

  1. 如果你的接口(抽象基類)被凍結,那麼你將不得不使用存儲或者打破你的用戶的兼容性。
  2. 爲避免強迫您的用戶登錄到#include <string><vector>
0

我認爲給子類訪問你的數據是可以的,如果你沒有把這個類作爲一個庫公開給其他子類。如果你真的想要或需要隱藏你的子類實際執行數據的,不過,你可以讓mData私人和創建存取它被保護:

class Base { 
protected: 
    // figure out what interface you want for your subclasses: 
    // do they need the whole enchilada? or can you give them 
    // a few more targeted kinds of modification routines? 
    // one example: 
    void add_data(const std::string& d) { mData.push_back(d); } 
private: 
    std::vector<std::string> mData; 
}; 
8

這是開放的相當大的爭論。允許數據爲protected被添加到C++很大程度上是因爲Mark Linton希望它用於他設計的Interviews Windowing庫。它看起來與C++的其餘設計非常吻合,所以(顯然)Bjarne贊同這個想法。幾年後,Mark因爲使用它們導致的錯誤數量而禁止在面試中使用受保護的數據成員。此後不久,芭芭拉·利斯科夫就整個概念談論了理論和實際問題。

的設計與C++演進,Bjarne的結論是:「現在回想起來,我認爲這protected這樣的情況,我讓‘很好的理由’與時尚克服我的判斷和接受新功能我的經驗法則「。底線:我有第二個和第三個想法來製作你的數據protected。它現在看起來可能是個好主意,但維護可能是一個完全不同的故事。

+0

非常感謝您的回覆和有趣的故事。是的,維護也是我關心的問題。我接受了其他答案,因爲user168715指出了一種解決問題的方法。 – EXP0 2010-06-15 19:28:33

1

我得出結論,受保護的數據和公共數據一樣糟糕。如果您需要更改受保護的數據,您將打破從基礎派生的所有類。這些派生類是您的基類的客戶,就像常規的「公共」用戶一樣。我建議編寫派生類可以調用的受保護的訪問函數。這爲您提供了所有公共成員函數的好處:您可以在不中斷客戶端的情況下更改實現,並且可以根據需要輕鬆添加檢測和錯誤檢查。