std :: string和std :: wstring的前向声明

Dan*_*per 5 c++ inheritance templates stdstring forward-declaration

经常讨论无法转发声明std :: string和std :: wstring的问题.据我所知,原因是这些类型是模板类basic_string实例化的typedefing:

namespace std {
  typedef basic_string<char>    string;
  typedef basic_string<wchar_t> wstring;
}
Run Code Online (Sandbox Code Playgroud)

语言不允许转发typedef的声明.

对于使用继承而不是typedef的c ++标准,这不是更好吗?

namespace std {
  class string : public basic_string<char> {};
  class wstring : public basic_string<wchar_t> {};
}
Run Code Online (Sandbox Code Playgroud)

那么我们可以转发声明std :: string和std :: wstring?

utn*_*tim 8

使用继承而不是typedef [...]的c ++标准会更好

没有.

std :: basic_string并不意味着以任何形式继承.这个限制允许实现std :: basic_string,因为它没有虚函数表,所以创建和销毁要便宜得多(更快).

如果你需要定义std :: [w]字符串,只需#include它.

编辑(回答评论)

C++(和标准库)的指导原则之一是"不为你不使用的东西买单".这意味着代码以这样的方式编写,您不应该为不需要的功能带来运行时成本.

如果每个实例都有一个虚拟表,那么创建一个std :: string实例将会更加昂贵(这将使得使用std :: string,这在性能关键代码中是禁止的).

相反,std :: string旨在作为C char*机制的快速,类型安全的RAII实现.同样,您不应该尝试从std :: vector,list,map,shared_ptr,unique_ptr等继承.

如果你真的需要一个字符串基类,可以考虑your_namespace::[w]string_base自己写一个(一个简单的实现将是一个封装std::[w]string内部的实现).

  • @utnapistim:不,继承在每种情况下都不需要虚拟析构函数.仅在需要多态删除时. (7认同)
  • 仅当定义了至少一个虚函数时,才存在虚函数表 (4认同)
  • @BenVoigt,技术上是的,但这意味着专业化不会实现多态删除。从库编写者的角度来看,这样的要求(比“不继承”)强加在客户端代码上要困难得多。最重要的是,没有人期望它(所以你正在增加代码的“WTF/SLOC”比率)。 (2认同)