2017-06-14 145 views
0

在C++編程語言,第4版,第20.5.2節「訪問基類」(第592頁)中,它說(關於私有繼承):通過限制 接口到基定義一個類時,使得強的保證可以是 provided.For例如如「C++編程語言」中所述的私有繼承用法

私人的鹼是最有用的,B是一個指針ž.The矢量 的實現細節從第25.3節向其向量基地 添加類型檢查的模板是一個好的例子mple。

現在還不清楚Bjarne Stroustrup在這裏想說些什麼。如何才能通過將「接口」限制在基礎上來定義類?他的「更強有力的保證」是什麼意思?

回答

3

讓作爲非常簡單的例子:

// A simple class with a *public* member 
class A 
{ 
public: 
    int a; 
}; 

// Use private inheritance 
class B : private A 
{ 
public: 
    int b; 
}; 

// Use public inheritance 
class C : public A 
{ 
public: 
    int c; 
}; 

// ... 

B my_b; 
my_b.a = 0; // Invalid, the member a is private due to the private inhericance 

C my_c; 
my_c.a = 0; // Valid, because the inheritance is public 

private繼承限制訪問基類的成員。即使A::a成員變量爲public,由於private繼承,它在子類B中變成private

0

怎樣才能通過限制「接口」基地來定義一個類?

通過使繼承是私人的。當繼承是私有的時,基類的接口僅限於成員函數,並且不在外部提供。訪問說明符可以在基地列表給出:

class A : private B 
//  ^^^^^^^ 

他對我們「做強保障」呢?

任何保證不是基數給出的,或者是基數給出的保證的超集。

例如,「的行爲始終是明確的」保障要強於「行爲被明確定義只有當輸入不爲空」。另一個例子:「函數不拋出」更強「除非複製構造函數拋出」,否則函數不會拋出。

+0

「只有當輸入不爲空時,行爲才被很好地定義」可能比「僅在輸入爲空時行爲才被良好定義」更好的示例;) – user463035818

+0

@ tobi303如果只有一個值,那麼輸入會有點無意義有效:D – user2079303

1

讓我們繼續向量的例子。矢量只是一個容器T s。現在讓我們假設您想要構建一個類似於矢量的類型,但會添加一些額外的運行時檢查。我現在手邊沒有我的TC++ PL副本,所以我們只需要制定一個約束:例如,假設您的向量只允許保存偶數。試圖插入一個奇數會導致運行時錯誤。我們稱之爲新類even_vector和沒有運行時檢查base_vector的版本。

even_vector提供了比base_vector更強大的運行時間保證:它保證它的所有元素均勻。

假設你base_vector設計工作作爲基類(std::vector通常不)不錯,你現在可能傾向於使用公有繼承在base_vector方面實現even_vector。畢竟,功能是相同的,只需在even_vector的情況下,在base_vector提供的功能基礎上進行一些額外的運行時檢查。但是,如果您要在此處使用公有繼承,那麼您將違反Liskov Substitution Principle:無論您使用base_vector的哪個位置,都不能使用even_vector。特別是,如果您將奇數插入base_vector,則even_vector會中斷。這是不好的,因爲現在所有爲base_vector編寫的代碼都必須考慮到某些base_vector不能處理奇數的事實。

對於私有繼承,您沒有這個問題:這裏even_vectorbase_vector繼承的事實是實現的細節。客戶端無法使用even_vector,因此預計會出現base_vector,所以上述問題不會發生,但我們仍然可以獲得代碼重用的好處。

這就是說,使用私有繼承進行代碼重用是許多人不鼓勵的做法。一個可以說更好的方法是use composition here instead,也就是說,將私人base_vector成員添加到even_vector。該方法的優點是嚴重減少了兩個類別之間的耦合,因爲even_vector不再能夠訪問base_vector的任何非公開部分。

0

允許我們查看接口的可能情況以幫助構建圖片。

class poison { 
    public: 
    virtual void used() = 0; 
}; 

class food { 
    public: 
    virtual void eat(); 
    protected: 
    void poisonConsumed(poison& p); 
} 

class cheese : public food, private poison { 
    public: 
    virtual void eat() override { 
     poisonConsumed(*this); 
    } 
    private: 
    void used() override; 
} 

這提出奶酪被外界看作「不是毒藥」 - 即沒有外部類可以知道這是一劑毒藥,而且它可以用它來製造「不是毒藥」對任何事情沒有影響。然而,奶酪可以將自己傳遞給任何期望毒藥的東西,然後可以自由調用used();即使它在奶酪中是私密的。