簡體   English   中英

從std :: basic_string的私有繼承

[英]Private inheritance from std::basic_string

我一直在嘗試了解有關私有繼承的更多信息,並決定創建一個從std::basic_string繼承的string_t類。 我知道很多人都會告訴我從STL類繼承是一個壞主意,如果我想擴展其功能,最好創建全局函數以接受對這些類實例的引用。 我同意,但是就像我之前說的,我正在嘗試學習如何實現私有繼承。

到目前為止,這是該類的樣子:

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 std::basic_string<value_type>::operator=; 線。 據我了解, using關鍵字指定將賦值運算符在string_t內從private范圍string_tpublic范圍。

為什么會出現此錯誤,我該如何解決?

另外,我的string_t類不包含它自己的單個數據成員,更不用說動態分配的成員了。 因此,如果我不為此類創建析構函數,那是否意味着如果有人要使用基類指針delete string_t實例, string_t調用基類析構函數?

當我為string_t定義了析構函數時,以下代碼引發異常,但是當我用VS2008編譯時將析構函數注釋掉時,以下代碼將起作用。

basic_string<wchar_t> *p = new string_t( L"Test" );
delete p;

您的默認構造函數不應是顯式的。 我認為明確可能是它也無法將std::string轉換為string_t的原因,但是您從代碼段:vP中刪除了該string_t

該程序可以在GCC 4.2上編譯並正常運行:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

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;

    for ( size_t pen = 0, next = 0; next != npos; pen = next + 1 ) {
        next = find_first_of( delims, pen );
        if ( pen != next ) tokens.push_back( substr( pen, next - pen ) );
    }
    return tokens;
  }

  template<class os>
  friend os &operator<<(os &, string_t const&);
};

template< class os_t >
os_t &operator<<( os_t &os, string_t const &str ) {
        return os << static_cast< string >(str);
}

int main( int argc, char ** argv ) {
        vector<string_t> mytoks = string_t( argv[1] ).split( string( "_" ) );

        for ( vector<string_t>::iterator it = mytoks.begin(); it != mytoks.end(); ++ it ) {
                cerr << * it << endl;
        }
        return 0;
}

您需要提供合適的轉換構造函數:

 string_t(const std::basic_string<value_type>&);

否則,編譯器不知道如何構建一個string_tstd::basic_string<>當你添加元素的矢量string_t秒。

關於更新:
如果operator=()是私有的,則using聲明無濟於事。 為什么不只是實現自己的operator=()而是轉發分配:

string_t& operator=(const string_t& s) 
{
    basic_string<value_type>::operator=(s); 
    return *this; 
}

有了它對我來說很好。

不幸的是,您已經遺漏了足夠多的信息,無法確定如何得到已記錄的錯誤消息(並且編譯時我們不知道657行是什么也無濟於事)。

當前可能似乎是substr()返回一個std :: string,並且編譯器不確定如何將其轉換為string_t (這就是您要它存儲在向量中的內容)。 您可能需要/想要添加一個ctor來處理此問題,例如:

string_t(std::string const &init) : std::string(init) {}

這樣一來,編譯器便知道如何將substr()返回的substr()轉換為string_t ,它可以根據您的請求將其推入向量中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM