【问题标题】:Is inheriting from std::basic_string ok? [duplicate]从 std::basic_string 继承好吗? [复制]
【发布时间】:2026-01-19 02:55:01
【问题描述】:

我在这里阅读了许多类似的问题,但我仍然不确定答案。我知道不鼓励从​​ STL 类派生,但 std::basic_string 似乎是一个不错的选择。

我面临的问题是 g++ 不合适,因为 std::basic_string 没有虚拟析构函数。为什么不是虚拟的? std::string 不是从它派生的吗?

一次尝试:

class string_t :
  private std::basic_string<char>
{
public:
   string_t() :
      basic_string<value_type>() {}

   string_t(
      const basic_string<value_type>& s) :
         basic_string<value_type>(s) {}

   virtual ~string_t() {}
};

另一个尝试:

class string_t :
   public std::basic_string<char>
{
public:
   virtual ~string_t();
};

使用 -Weffc++ 编译时都会抛出此警告:

警告:基类 'class std::basic_string' 有一个非虚拟 析构函数

【问题讨论】:

  • std::stringstd::basic_string,字符类型是 char,不是派生类。您不能从模板派生,因为模板不是类型。你实际上是从std::string这里派生的。
  • std::string 是 typedef,而不是派生类。不,从其中任何一个派生都是不行的。
  • " 不鼓励使用 STL 类,但 std::basic_string" 我认为这是正确的,直到最近有人向我澄清说,从例如私有继承是完全可以的。标准::向量。我不是 100% 肯定,但我想一般情况下是这样的:stl 类并不打算用作公共基类。 (期待得到更正,以防这也不完全正确)
  • FWIW,请记住这是从 2012 年开始的,this answer 解释说 -Weffc++ 有几个问题,the comment 在它下面特别指出了这个问题(用于私有继承)。无论如何,请记住,私有或公共的继承会导致两个类之间的极端耦合。如果有不同的可行解决方案,比如组合,通常是首选。
  • 你为什么要做这样的事情?

标签: c++ inheritance stl g++


【解决方案1】:

好吧,STL 类并未设计为可继承。继承std::string 和其他的主要问题是它们没有虚拟析构函数。对于公共继承的基类来说,这是一个很大的禁忌,因为警告清楚地表明了这一点。不过,对于私有继承来说,这几乎没有那么危险。

bug report 在私有继承具有非虚拟析构函数的基类的情况下不会发出错误。它没有被标记为已修复,但是我的测试表明在 g++ 4.9.2 中没有发出带有私有继承的警告。

此外,错误中的一条注释显示了如何使用(故意?)错误代码射击自己的脚:

class Foo {
public:
    ~Foo() {}
    virtual void f() { }
};

class Bar : private Foo {
public:
    Foo* get() { return this; }
};

int main()
{
    Bar* b = new Bar;
    delete b->get();
}

如果您避免像上面的 sn-p 那样在类之外暴露继承关系,那么使用非虚拟析构函数私有继承一个类也不错。如果不详细说明您将如何使用继承,则无法说这是否是最佳方法。

std::string 不是从它派生的吗?

不,std::stringstd::basic_string&lt;char&gt; 的别名。

【讨论】: