我一直在嘗試學習更多關於私有繼承的知識,並決定創建一個string_t
類,它繼承自std::basic_string
。我知道很多你會告訴我從STL類繼承是一個壞主意,如果我想擴展它們的功能,最好創建接受對這些類的實例的引用的全局函數。我同意,但正如我之前所說,我正試圖學習如何實現私有繼承。來自std :: basic_string的私有繼承
這是類的樣子至今:
class string_t :
#if defined(UNICODE) || defined(_UNICODE)
private std::basic_string<wchar_t>
#else
private std::basic_string<char>
#endif
{
public:
string_t() : basic_string<value_type>() {}
string_t(const basic_string<value_type>& str)
: basic_string<value_type>(str) {}
virtual ~string_t() {}
using std::basic_string<value_type>::operator=; /* Line causing error */
std::vector<string_t> split(const string_t& delims)
{
std::vector<string_t> tokens;
tokens.push_back(substr(0, npos));
}
};
我收到以下錯誤:
1>c:\program files\microsoft visual studio 9.0\vc\include\xutility(3133) : error C2243: 'type cast' : conversion from 'const string_t *' to 'const std::basic_string &' exists, but is inaccessible 1> with 1> [ 1> _Elem=wchar_t, 1> _Traits=std::char_traits, 1> _Ax=std::allocator 1> ] 1> c:\program files\microsoft visual studio 9.0\vc\include\xutility(3161) : see reference to function template instantiation 'void std::_Fill(_FwdIt,_FwdIt,const _Ty &)' being compiled 1> with 1> [ 1> _Ty=string_t, 1> _FwdIt=string_t * 1> ] 1> c:\program files\microsoft visual studio 9.0\vc\include\vector(1229) : see reference to function template instantiation 'void std::fill(_FwdIt,_FwdIt,const _Ty &)' being compiled 1> with 1> [ 1> _Ty=string_t, 1> _FwdIt=string_t * 1> ] 1> c:\program files\microsoft visual studio 9.0\vc\include\vector(1158) : while compiling class template member function 'void std::vector::_Insert_n(std::_Vector_const_iterator,unsigned int,const _Ty &)' 1> with 1> [ 1> _Ty=string_t, 1> _Alloc=std::allocator 1> ] 1> c:\work\c++\string_t\string_t.h(658) : see reference to class template instantiation 'std::vector' being compiled 1> with 1> [ 1> _Ty=string_t 1> ]
中的最後一個錯誤點的行號(658)來的左括號split()
函數定義。如果我註釋掉using std::basic_string<value_type>::operator=;
這一行,我可以擺脫這個錯誤。據我所知,using
關鍵字指定賦值運算符從private
到public
範圍內的string_t
。
爲什麼我得到這個錯誤,我該如何解決?
此外,我的string_t
類不包含它自己的單個數據成員,更不用說任何動態分配的成員。所以如果我不爲這個類創建一個析構函數並不意味着如果有人使用基類指針的一個實例,基類的析構函數會被調用?
下面的代碼在我爲string_t
定義析構函數時會拋出異常,但在使用VS2008編譯時註釋掉析構函數時會發生異常。
basic_string<wchar_t> *p = new string_t(L"Test");
delete p;
你不覺得你會用它的東西,你*不*都不理大家的意見更多地瞭解私有繼承? ;) – jalf 2010-01-08 12:23:23
私有繼承通常是一個壞主意。使用它的唯一理由是應用EBO優化(空基優化),並且由於'std :: string'有數據,所以它不具備資格。所有其他「原因」(如虛擬重定義)都有其他解決方案(在這種情況下,公共繼承+組合)。繼承是一個非常強大的關係,特別是在知名度方面,它比友誼好,但不是太多。對於這個問題,你可以完美地添加自由函數來擴展接口。 – 2010-01-08 17:46:02
@Matthieu - 在這種情況下公共繼承的問題是std :: basic_string沒有虛擬析構函數;因此試圖使用基類指針刪除string_t的實例會導致內存泄漏。也許你可以回答第二個問題:如果string_t類不需要析構函數而不聲明它,那麼我提到的使用delete的問題是否仍然存在? – Praetorian 2010-01-08 18:23:31