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

C++ std::basic_字符串的私有继承,c++,inheritance,stl,C++,Inheritance,Stl,我一直在努力学习有关私有继承的更多信息,并决定创建一个从std::basic\u string继承的string\t类。我知道很多人会告诉我从STL类继承是个坏主意,如果我想扩展它们的功能,最好只创建全局函数来接受对这些类实例的引用。我同意,但正如我前面所说,我正在努力学习如何实现私有继承 到目前为止,这门课是这样的: class string_t : #if defined(UNICODE) || defined(_UNICODE) private std::basic_string<

我一直在努力学习有关私有继承的更多信息,并决定创建一个从std::basic\u 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 ) );
  }
};

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

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

这对我来说很好。

不幸的是,你漏掉了足够多的信息,不确定你是如何得到你注意到的错误消息的,我们不知道你编译它时第657行是什么,这没有帮助

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

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

这使编译器知道如何将substr返回的字符串转换为一个字符串,它可以根据您的请求将其推入向量。

默认构造函数不应是显式的。我认为明确性可能是它无法将std::string转换为string\t的原因,但是您从代码段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;
}

我已经有了如下定义的构造函数:string\u tconst std::basic\u string&:basic\u string{}对不起,我对模板比较陌生,所以我可能遗漏了一些明显的东西为什么不给我们一个小的可编译示例来展示这个问题呢?添加转换构造函数使代码对我来说是可编译的,并且没有显示您提到的第一个问题。转换不应该是私有的。他遇到了问题,因为转换存在,但无法访问;v@gf-我发布了一个可编译的示例,其中显示了错误,并跟踪了导致错误的行。对于行号,很抱歉,657行是定义拆分函数的行,准确地说,是包含大括号的行。我有一个如下定义的转换构造函数:string\u tconst std::basic\u string&:basic\u string{}这不应该和你说的一样吗?不,它接受std::basic\u string作为参数,但无法将参数传递给基类。抱歉,这只是一个输入错误。构造函数实际上被定义为:string_t const basic_string&str:basic_string str{}你不认为你可以通过将私有继承用于一些不必忽略所有人建议的事情来了解更多关于私有继承的信息吗;私人继承通常是个坏主意。使用它的唯一原因是让EBO优化应用空基优化,因为std::string有数据,所以它不合格。所有其他的原因,比如虚拟重新定义,都有其他的解决方案,在这种情况下,公共继承+组合。继承是一种非常牢固的关系,尤其是在可视性方面,它比友谊要好,但不是很多。对于这个问题,您可以完美地添加自由函数来扩展接口。@Matthieu-这种情况下公共继承的问题是std::basic_字符串没有虚拟析构函数;因此,尝试使用基类指针删除string_t的实例将导致内存泄漏。也许你可以回答第二个问题:如果string_t类不需要析构函数,也不声明析构函数,那么我提到的delete问题是否仍然存在?@praetorian:你是对的,如果string的析构函数足够,就不应该有问题。顺便说一下,你的代码是为我编译的。我还充实了它,并对它进行了测试;一切都应该很好。@praetorian:更新了答案。我复制粘贴了你的代码并试图编译它,但VS2008给了我同样的错误!
string_t& operator=(const string_t& s) 
{
    basic_string<value_type>::operator=(s); 
    return *this; 
}
string_t(std::string const &init) : std::string(init) {}
#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;
}