代码之家  ›  专栏  ›  技术社区  ›  Praetorian Luchian Grigore

std::basic_字符串的私有继承

  •  2
  • Praetorian Luchian Grigore  · 技术社区  · 15 年前

    我一直在尝试了解更多关于私有继承的信息,并决定创建一个 string_t 继承自的类 std::basic_string . 我知道很多人会告诉我从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 关键字指定赋值运算符是从 private public 范围内 字符串 .

    为什么我会得到这个错误,我如何修复它?

    还有,我的 斯特林格 类不包含它自己的单个数据成员,更不用说任何动态分配的成员了。所以如果我不为这个类创建一个析构函数,这并不意味着如果有人 delete 一个实例 斯特林格 使用基类指针将调用基类析构函数?

    当我为定义了析构函数时,以下代码将引发异常 斯特林格 但是当我在用vs2008编译时注释掉析构函数时,它是有效的。

    basic_string<wchar_t> *p = new string_t( L"Test" );
    delete p;
    
    3 回复  |  直到 15 年前
        1
  •  3
  •   Potatoswatter    15 年前

    您的默认构造函数不应该是显式的。我认为直言不讳可能是它无法转换的原因 std::string string_t 同样,但是你从你的代码片段中删除了construtor:vp。

    该程序编译并运行良好,符合GCC4.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;
    }
    
        2
  •  2
  •   Georg Fritzsche    15 年前

    您需要提供适当的转换构造函数:

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

    否则编译器不知道如何构造 string_t 从A std::basic_string<> 当你将元素添加到 斯特林格 S.

    关于更新:
    A using 声明 operator=() 如果是私人的就没用了。为什么不实施你自己的 运算符=() 而是转发任务:

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

    这样对我来说很好。

        3
  •  0
  •   Jerry Coffin    15 年前

    不幸的是,您遗漏了足够多的信息,以至于无法确定您是如何收到所注意到的错误消息的(而且,当您编译第657行时,我们不知道它是什么,这也无济于事…)。

    目前可能是 substr() 返回一个std::string,编译器不确定如何将其转换为 string_t (这就是你要求它存储在向量中的内容)。您可能需要/希望添加一个ctor来处理此问题,例如:

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

    这使编译器知道如何转换 子() 变成一个 斯特林格 它可以按您的要求推入向量。