在C++編程語言,第4版,第20.5.2節「訪問基類」(第592頁)中,它說(關於私有繼承):通過限制 接口到基定義一個類時,使得強的保證可以是 provided.For例如如「C++編程語言」中所述的私有繼承用法
私人的鹼是最有用的,B是一個指針ž.The矢量 的實現細節從第25.3節向其向量基地 添加類型檢查的模板是一個好的例子mple。
現在還不清楚Bjarne Stroustrup在這裏想說些什麼。如何才能通過將「接口」限制在基礎上來定義類?他的「更強有力的保證」是什麼意思?
在C++編程語言,第4版,第20.5.2節「訪問基類」(第592頁)中,它說(關於私有繼承):通過限制 接口到基定義一個類時,使得強的保證可以是 provided.For例如如「C++編程語言」中所述的私有繼承用法
私人的鹼是最有用的,B是一個指針ž.The矢量 的實現細節從第25.3節向其向量基地 添加類型檢查的模板是一個好的例子mple。
現在還不清楚Bjarne Stroustrup在這裏想說些什麼。如何才能通過將「接口」限制在基礎上來定義類?他的「更強有力的保證」是什麼意思?
讓作爲非常簡單的例子:
// 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
。
怎樣才能通過限制「接口」基地來定義一個類?
通過使繼承是私人的。當繼承是私有的時,基類的接口僅限於成員函數,並且不在外部提供。訪問說明符可以在基地列表給出:
class A : private B
// ^^^^^^^
他對我們「做強保障」呢?
任何保證不是基數給出的,或者是基數給出的保證的超集。
例如,「的行爲始終是明確的」保障要強於「行爲被明確定義只有當輸入不爲空」。另一個例子:「函數不拋出」比更強「除非複製構造函數拋出」,否則函數不會拋出。
讓我們繼續向量的例子。矢量只是一個容器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_vector
從base_vector
繼承的事實是實現的細節。客戶端無法使用even_vector
,因此預計會出現base_vector
,所以上述問題不會發生,但我們仍然可以獲得代碼重用的好處。
這就是說,使用私有繼承進行代碼重用是許多人不鼓勵的做法。一個可以說更好的方法是use composition here instead,也就是說,將私人base_vector
成員添加到even_vector
。該方法的優點是嚴重減少了兩個類別之間的耦合,因爲even_vector
不再能夠訪問base_vector
的任何非公開部分。
允許我們查看接口的可能情況以幫助構建圖片。
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();即使它在奶酪中是私密的。
「只有當輸入不爲空時,行爲才被很好地定義」可能比「僅在輸入爲空時行爲才被良好定義」更好的示例;) – user463035818
@ tobi303如果只有一個值,那麼輸入會有點無意義有效:D – user2079303