2012-04-09 38 views
1

我有一個Message類的對象,它可以被寫入並隨後被更新。據我所看到的,MessageUpdate IS-A內留言:C++:在派生類中限制方法訪問

class MessageWrite 
{ 
    protected: 
    void setVersion(int version_) {...} 
    void setReceiveTime(int tmReceive_) {...} 

    Message _msg; 
}; 


class MessageUpdate:public MessageWrite 
{ 
    //ONLY setVersionShould be accessible here, NOT setReceiveTime 
}; 

有沒有方法訪問級別和繼承級別的組合,可以幫助實現這一目標?

我知道MessageUpdate可以簡單地做成基類,但這裏有一點:如果我想擴展消息類,它會導致菱形模式。考慮:

class MessageUpdate {...}; 
class MessageWrite: public MessageUpdate {...}; 


//Now, while extending: 
class AdminMessageUpdate:public MessageUpdate {...}; 
class AdminMessageWrite: public AdminMessageUpdate, public MessageWrite //DIAMOND Pattern!! 

哪裏有我對遺傳理解的差距?是否有完全不同的方式來實現這種邏輯沒有多重繼承(如後面的代碼片段所示)?

+0

菱形圖案是隻要OK [虛擬繼承] (http://en.wikipedia.org/wiki/Virtual_inheritance)。 – dasblinkenlight 2012-04-09 14:10:18

+0

有關使用虛擬基類的示例,請參閱http://stackoverflow.com/a/21607/13140以確保您的繼承樹中不會獲得「MessageWrite」的多個副本。所以你想只有MessageWrite能夠調用setReceiveTime()? – 2012-04-09 14:15:58

+0

感謝dasblinkenlight,但我更喜歡@Als的方法,因爲它可以節省多重繼承的運行時成本 – vid 2012-04-09 14:16:44

回答

1

由於MessageWrite所有成員都protected,你可以只讓setReceiveTime()privateMessageUpdate,所以從類繼承MessageUpdate不就能夠訪問它。但我的設計仍然存在一些問題,例如:

您的設計如何避免鑽石?那豈不是同樣導致:

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessageWrite:public MessageWrite {...}; 
class AdminMessageUpdate: public AdminMessageWrite, public MessageUpdate //DIAMOND Pattern!! 

爲什麼你認爲MessageUpdate IS-A MessageWrite,當你以後說這不是(通過指定,並非所有的MessageWrite適用於它)?如果這個代碼必須是有效的:

MessageWrite& m = MessageUpdate(); 
m.setReceiveTime(); // Should this be valid? 

然後MessageUpdate IS-NOT-A MessageWrite。如果我的代碼應該是有效的,那麼沒有理由避免訪問MessageUpdate中的setReceiveTime()

而且你很可能是通過創建一個基類AdminMessage,然後直接從它繼承更好,避免鑽石:你不怕

class MessageWrite {...}; 
class MessageUpdate: public MessageWrite {...}; 

//Now, while extending: 
class AdminMessage {...}; 
class AdminMessageWrite: public MessageWrite, public AdminMessage {...}; 
class AdminMessageUpdate: public MessageUpdate, public AdminMessage {...}; // No diamond 
0

保護:繼承的成員可以訪問。

私有:繼承的成員無法訪問。

protected: 
    void setVersion(int version_) {...} 
    private: 
    void setReceiveTime(int tmReceive_) {...} 
2

只是聲明方法:

private: 
void setReceiveTime(int tmReceive_); 

與基類MessageWriteprivate訪問符。

我這個答案應該是一個良好的閱讀:

What are access specifiers? Should I inherit with private, protected or public?

+0

處調用setReceiveTime(),謝謝,這就是發現。我無法自動做到這一點?必須重寫所有方法聲明? – vid 2012-04-09 14:11:20

+0

@vid:您必須手動執行此操作。此外,類成員的訪問說明符在方法聲明的類定義中指定。請注意,通常,類方法在頭文件中聲明*,在cpp文件中定義*。 – 2012-04-09 14:13:26

1

如果MessageUpdate是-A MessageWrite,然後通過定義,它可以訪問所有的protected和public成員。

所以,如果有要公開/ protectedly暴露在MessageWrite,你不希望在MessageUpdate暴露的成員,然後由Liskov Substitution PrincipleMessageUpdate不能是MessageWrite

+0

+1原則 – vid 2012-04-09 14:18:51