简体   繁体   English

从std :: basic_string的私有继承

[英]Private inheritance from std::basic_string

I've been trying to learn more about private inheritance and decided to create a string_t class that inherits from std::basic_string . 我一直在尝试了解有关私有继承的更多信息,并决定创建一个从std::basic_string继承的string_t类。 I know a lot of you will tell me inheriting from STL classes is a bad idea and that it's better to just create global functions that accept references to instances of these classes if I want to extend their functionality. 我知道很多人都会告诉我从STL类继承是一个坏主意,如果我想扩展其功能,最好创建全局函数以接受对这些类实例的引用。 I agree, but like I said earlier, I'm trying to learn how to implement private inheritance. 我同意,但是就像我之前说的,我正在尝试学习如何实现私有继承。

This is what the class looks like so far: 到目前为止,这是该类的样子:

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 ) );
  }
};

I get the following errors: 我收到以下错误:

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>        ]

The line number (658) in the last error points to the opening brace of the split() function definition. 最后一个错误中的行号(658)指向split()函数定义的左括号。 I can get rid of the error if I comment out the using std::basic_string<value_type>::operator=; 如果我注释掉using std::basic_string<value_type>::operator=;的错误,我可以摆脱using std::basic_string<value_type>::operator=; line. 线。 As I understand it, the using keyword specifies that the assignment operator is being brought from private to public scope within string_t . 据我了解, using关键字指定将赋值运算符在string_t内从private范围string_tpublic范围。

Why am I getting this error and how can I fix it? 为什么会出现此错误,我该如何解决?

Also, my string_t class doesn't contain a single data member of it's own, much less any dynamically allocated members. 另外,我的string_t类不包含它自己的单个数据成员,更不用说动态分配的成员了。 So if I don't create a destructor for this class doesn't that mean that if someone were to delete an instance of string_t using a base class pointer the base class destructor would be called? 因此,如果我不为此类创建析构函数,那是否意味着如果有人要使用基类指针delete string_t实例, string_t调用基类析构函数?

The following code throws an exception when I have a destructor defined for string_t but works when I comment out the destructor when compiled with VS2008. 当我为string_t定义了析构函数时,以下代码引发异常,但是当我用VS2008编译时将析构函数注释掉时,以下代码将起作用。

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

Your default constructor should not be explicit. 您的默认构造函数不应是显式的。 I think explicitness may be the reason it can't convert std::string to string_t as well, but you erased that construtor from your snippet :vP . 我认为明确可能是它也无法将std::string转换为string_t的原因,但是您从代码段:vP中删除了该string_t

This program compiles and runs fine with GCC 4.2: 该程序可以在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;
}

You need to provide a suitable conversion constructor: 您需要提供合适的转换构造函数:

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

Otherwise the compiler doesn't know how to construct a string_t from a std::basic_string<> when you're adding elements to the vector of string_t s. 否则,编译器不知道如何构建一个string_tstd::basic_string<>当你添加元素的矢量string_t秒。

Regarding the update: 关于更新:
A using declaration for operator=() doesn't help if it is private. 如果operator=()是私有的,则using声明无济于事。 Why not just implement your own operator=() instead and forward the assignment: 为什么不只是实现自己的operator=()而是转发分配:

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

With that it builds fine for me. 有了它对我来说很好。

Unfortunately, you've left out enough that it's uncertain how you're getting the error message you've noted (and it doesn't help that we don't know what was line 657 when you compiled it...). 不幸的是,您已经遗漏了足够多的信息,无法确定如何得到已记录的错误消息(并且编译时我们不知道657行是什么也无济于事)。

The probably currently appears to be that substr() is returning an std::string, and the compiler isn't sure how to convert that to a string_t (which is what you're asking it to store in the vector). 当前可能似乎是substr()返回一个std :: string,并且编译器不确定如何将其转换为string_t (这就是您要它存储在向量中的内容)。 You probably need/want to add a ctor to handle this, something like: 您可能需要/想要添加一个ctor来处理此问题,例如:

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

That lets the compiler know how to convert the string returned by substr() into a string_t that it can push into the vector as you requested. 这样一来,编译器便知道如何将substr()返回的substr()转换为string_t ,它可以根据您的请求将其推入向量中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM