C ?protected繼承和private繼承是不是沒用的廢物?
[導(dǎo)讀]如圖是真實世界實踐中C項目protected繼承和private繼承的情況:其中public繼承總的平均下來幾乎占99.9%,而protected繼承幾乎沒有。private繼承還能占極小部分,但也完全可以用public繼承復(fù)合取代。實踐是檢驗真理的唯一標(biāo)準(zhǔn),現(xiàn)實世界中的這些項目...
如圖是真實世界實踐中C 項目protected繼承和private繼承的情況: 其中public繼承總的平均下來幾乎占99.9%,而protected繼承幾乎沒有。private繼承還能占極小部分,但也完全可以用public繼承 復(fù)合取代。實踐是檢驗真理的唯一標(biāo)準(zhǔn),現(xiàn)實世界中的這些項目情況是否能說明protected繼承和private繼承是沒用的廢物?是只會出現(xiàn)在語法理論和教科書中的垃圾嗎?
既然你所統(tǒng)計的項目里出現(xiàn)了 private 繼承和 protected 繼承,這不正說明確實有他們的用武之地嗎?
讓我們來康康 C 代碼的標(biāo)桿——STL 的源碼,是怎么做的:
先來康 GCC 自帶的 libstdc 的實現(xiàn):vector:
list:
deque:
forward_list:
unordered_(multi)set/map 的底層 Hashtable:
tuple 雖然是直接繼承自 Tuple_impl:
但 Tuple_impl 是用到了 private 繼承展開各個字段的:
pair:
mutex:
functional:
bitset:
再來康 Clang 自帶的實現(xiàn),libc 的:vector:
list:
string:
tuple 底層用于空基類壓縮優(yōu)化的:
其他的類似,我就不繼續(xù)展開了,否則你這月流量不夠了
最后康 MSVC 的:MSVC STL 雖然幾個容器模板沒有用到繼承,但至少 tuple 和 varient 還是挺給我面子的:tuple:
varient:
看吧,protected private 繼承用的多普遍,更多的我還沒列舉完~
1)很多人說你用 protected private 繼承倒不如用組合,把原本的基類作為一個私有或保護(hù)字段。這種論調(diào)是很沒有道理的。很多時候,繼承是替代不了的。比如 C 里有一種非常常見的優(yōu)化技術(shù)叫:
他就只能用繼承去實現(xiàn);而使用組合時,就沒有壓縮的效果。
考察下面代碼,這是對 vector 壓縮 allocator 字段原理的簡化實現(xiàn):
作者:IceBear
來源:https://www.zhihu.com/question/425852397/answer/1528656579
〇、引言
既然你所統(tǒng)計的項目里出現(xiàn)了 private 繼承和 protected 繼承,這不正說明確實有他們的用武之地嗎?
一、現(xiàn)有項目分析(以 STL 的三大實現(xiàn)為例)
讓我們來康康 C 代碼的標(biāo)桿——STL 的源碼,是怎么做的:
先來康 GCC 自帶的 libstdc 的實現(xiàn):vector:
list:
deque:
forward_list:
unordered_(multi)set/map 的底層 Hashtable:
tuple 雖然是直接繼承自 Tuple_impl:
但 Tuple_impl 是用到了 private 繼承展開各個字段的:
pair:
mutex:
functional:
bitset:
再來康 Clang 自帶的實現(xiàn),libc 的:vector:
list:
string:
tuple 底層用于空基類壓縮優(yōu)化的:
其他的類似,我就不繼續(xù)展開了,否則你這月流量不夠了
最后康 MSVC 的:MSVC STL 雖然幾個容器模板沒有用到繼承,但至少 tuple 和 varient 還是挺給我面子的:tuple:
varient:
二、protected private 繼承的實際運用場景考察
1)很多人說你用 protected private 繼承倒不如用組合,把原本的基類作為一個私有或保護(hù)字段。這種論調(diào)是很沒有道理的。很多時候,繼承是替代不了的。比如 C 里有一種非常常見的優(yōu)化技術(shù)叫:
空基類壓縮優(yōu)化技術(shù)
他就只能用繼承去實現(xiàn);而使用組合時,就沒有壓縮的效果。
考察下面代碼,這是對 vector 壓縮 allocator 字段原理的簡化實現(xiàn):
class MyAllocator{};
template <typename T, typename Allocator = MyAllocator>class MyVector: public Allocator{};
void use_allocator(const MyAllocator 




