来自std :: basic_string的私有继承

时间:2010-01-08 05:52:57

标签: c++ inheritance stl

我一直在努力了解有关私有继承的更多信息,并决定创建一个继承自string_t的{​​{1}}类。我知道很多人会告诉我继承STL类是一个坏主意,如果我想扩展它们的功能,最好只创建接受对这些类实例的引用的全局函数。我同意,但正如我之前所说,我正在努力学习如何实现私有继承。

到目前为止,这是该课程的样子:

std::basic_string

我收到以下错误:

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)指向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 ) ); } }; 函数定义的左括号。如果我注释掉split()行,我可以摆脱错误。据我了解,using std::basic_string<value_type>::operator=;关键字指定赋值运算符从using范围内的private范围转移到public

为什么我收到此错误,我该如何解决?

此外,我的string_t类不包含它自己的单个数据成员,更不用说动态分配的成员了。所以,如果我没有为这个类创建析构函数,这并不意味着如果有人使用基类指针string_t delete的实例,那么将调用基类析构函数?

当我为string_t定义析构函数时,以下代码抛出异常,但在使用VS2008编译时注释掉析构函数时会起作用。

string_t

3 个答案:

答案 0 :(得分:3)

您的默认构造函数不应该是显式的。我认为明确可能是它无法将std::string转换为string_t的原因,但是你从你的代码段中删除了这个construtor:vP。

该程序使用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;
}

答案 1 :(得分:2)

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

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

否则,当您向string_t s的向量添加元素时,编译器不知道如何从std::basic_string<>构造string_t

关于更新:
using的{​​{1}}声明如果是私有的则无效。为什么不改为实现自己的operator=()并转发作业:

operator=()

有了它,它对我来说很好。

答案 2 :(得分:0)

不幸的是,你已经遗漏了很多,你不确定你是如何得到你注意到的错误信息的(当你编译它时我们不知道第657行是什么并没有帮助... )。

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

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

这让编译器知道如何将substr()返回的字符串转换为string_t,它可以按照您的请求将其推送到向量中。