2011-10-27 100 views
9

我正在閱讀std::sub_match<BidirectionalIterator>的文檔,看到它公開繼承std::pair<BidirectionalIterator, BidirectionalIterator>。由於一個sub_match只是一對迭代器到字符序列中,並且有一些額外的功能,我可以理解它是用pair實現的,但是爲什麼使用公共繼承?爲什麼std :: sub_match <T>公開繼承std :: pair <T, T>?

公開從std::pair<T,U>公開繼承的問題與從大多數其他標準類公開繼承的問題相同:它們不是要被多形地操縱(特別是它們沒有定義虛擬析構函數)。其他成員也將無法正常工作,即分配操作員和交換成員功能(他們不會複製成員sub_match)。

爲什麼boost開發,然後委員會決定由pair公開繼承,而不是使用成分(或私有繼承使用聲明,如果他們想通過firstsecond保持成員訪問)來實現sub_match

回答

5

這是一個有趣的問題。據推測,他們認爲這是安全的,因爲沒有人會動態地分配一個。關於你會得到sub_match對象 唯一的辦法就是從一些的basic_regex的功能,返回值 或作爲其他 sub_match副本和所有的這些都將是要麼臨時工或局部 變量。

請注意,這不是安全,保持sub_match對象周圍無論如何,因爲 它們含有迭代器,其一生......似乎並沒有在 標準指定。直到match_results對象被重用?直到 string操作數到填充在0​​ 對象被破壞的功能?要麼?

我仍然避免了公共繼承。但在這種情況下, 並不像看起來那麼危險,因爲你真的沒有理由想要 想要動態分配sub_match

+0

我同意應該可能永遠不會發生的動態分配。但是,使用'='和'swap'仍然可能會出現問題。例如,我在考慮Boost.Range,但它不要求範圍是Assignable或Swappable。然而,值得注意的是,Boost.Range算法不接受'sub_match'作爲參數,但如果通過引用'pair'(特徵類問題)來操作它們,則這樣做是有用的。 –

0

因爲他們不需要虛擬析構函數嗎? ;-)

+0

析構函數不是唯一不能正常工作的成員:賦值運算符和交換將只複製'pair'成員,而不是'sub_match'(包含'matched'布爾值)包含的成員。 –

+0

作者顯然認爲他們不需要虛擬析構函數,或者他們會提供一個虛擬析構函數。但是爲什麼呢,因爲在大多數情況下,公共繼承意味着需要在基類中使用虛擬析構函數。 –

+0

@LucTouraille好點。很明顯,沒有意圖'sub_match'是一個'pair'。 –

0

如果std::sub_match<BidirectionalIterator>沒有自己的狀態,那麼它可以繼承std::pair。儘管如此,不要在家裏做。

+0

狀態與它無關。如果你通過'pair <>'指針刪除了一個'sub_match'對象,那麼它就是未定義的行爲。 –

+1

此外,它確實有它自己的狀態(一個布爾值,指示匹配是否成功)。 –

3

這裏是regex的作者有話要說一下:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1429.htm#matches_discussion

沒有非常具體的你的問題,我很害怕。

我猜想這個決定是在重新發明輪子和引入誤用的一點風險之間進行權衡。請注意,通常不需要構建一個sub_match,它們是從regex函數返回的。而且迭代器對是實現範圍的一種非常實用的方法。

3

因爲C++無法繼承沒有公共繼承的接口。你可以繼承一個具有私有繼承的實現,但是所有事情都是私有的。如果需要與std::pair相同的接口,則必須 a std::pair

另外,請考慮這一點。這顯然是不確定的行爲:

std::sub_match<BidirectionalIterator> theMatch = ...; 
std::pair<BidirectionalIterator> *pMatch = &theMatch; 
delete pMatch; 

但這樣是這樣的:

std::sub_match<BidirectionalIterator> theMatch = ...; 
std::pair<BidirectionalIterator> *pMatch = &theMatch.pair; 
delete pMatch; 

爲什麼是第一個這麼多比第二關注的?

sub_matchpair是重量輕的物體(當然取決於它們的內容)。它們旨在被複制或通過引用傳遞,所有這些都是100%安全的。沒有什麼理由在堆上分配它們並通過指針使用它們。所以,雖然我理解你的擔憂,但我認爲這不太可能發生在任何真實的代碼中。

+0

事實上,你的第二個例子(幾乎)與第一個例子一樣有缺陷,但這是因爲你認爲'pair'成員是公開的:你爲什麼會認爲會使用這種不好的封裝?雖然我同意刪除可能永遠不會成爲問題,但我不同意通過引用傳遞是100%安全的,因爲其他非虛擬成員函數。 –

+0

您*可以*使用私有繼承繼承(部分)公共接口:'class sub_match:pair {using pair。第一;使用pair.second;布爾匹配; }' – JohannesD

+0

如果您希望將相同的接口作爲'std :: pair'而不是一個接口,那麼您可以使用私有繼承以及使用聲明和/或委派。當然,這對於這個子類的開發者來說是更多的工作。 –

相關問題