c 中的名称隐藏式成员功能:良好实践

Name-hiding static member functions in C++: good practice?

本文关键字:功能 成员 隐藏      更新时间:2023-10-16

在我作为C 程序员的时间中,我通常认为应该避免使用名称,因为它会导致混乱。例如,如果您的基类带有函数f()和带有函数f()的派生类,而f()不是虚拟的,则呼叫者可能会意外地调用错误的f()。

但是,我在阅读Herb Sutter的出色C 书籍时遇到了一个榜样,其中似乎鼓励了一个名字隐藏的案例。为了制作一个不敏感的字符串,他建议我们通过创建一个从char_traits<char>继承的char_traits类(这是一个非polymormormortic static类)来制作std::basic_string<>的不敏感版本,例如:

struct ci_char_traits : public char_traits<char>
{
  static bool eq( char c1, char c2 ) { /*...*/ }
  static bool lt( char c1, char c2 ) { /*...*/ }
  static int compare( const char* s1,
                      const char* s2,
                      size_t n)       { /*...*/ }
  static const char*
  find( const char* s, int n, char a ) { /*...*/ }
}

(我遗漏了功能定义,以使其更简洁)。本质上,我们正在继承char_traits<char>的所有功能,并且我们正在隐藏要修改的功能,以使其对病例不敏感。然后,您像这样定义了不敏感的字符串:

typedef basic_string<char, ci_char_traits> ci_string;

现在,我确实认为这是一个非常整洁的技巧!但是我想知道这种事情是否被认为是"好练习",因为通常会皱眉。命名隐藏静态成员函数比其他类型的功能更容易接受?

这里的区别在于特质类不是多态,因此永远不会对使用哪个接口进行任何混淆。

ci_char_traits当然可以用私有继承,封装或简单地将其推迟到std::char_traits<>来实现。所有这些方法都需要更多的维护。

更新:

评论中有关模板是否是多态的讨论。我会详细说明。

构造std::basic_string<char, ci_char_traits>导致模板std::basic_string<class CharT, class Traits, class Allocator>的模板扩展。在此扩展过程中,进行了以下类型的替换:

  • CharTchar
  • 替换
  • Traitsci_char_traits
  • 替换
  • Allocatorstd::allocator<char>
  • 替换

因此,编译器生成的类是:

std::basic_string<char, ci_char_traits, std::allocator<char>>

这不是多态类。

此类将具有称为 std::basic_string<char, ci_char_traits, std::allocator<char>>::traits_type的成员Typedef,它明确是ci_char_traits类型。

因此,此模板的扩展将导致非晶状体类别,该类别使用非造型类ci_char_traits来确定基于字符的操作的行为,例如比较。

eqlt的哪种过载可以通过类std::basic_string<char, ci_char_traits, std::allocator<char>>中的代码调用,这就是为什么在这种情况下,超载这些静态成员函数的习惯不是不好的做法。

在不敏感的示例中,这更重要的是实现接口,这只是碰巧的是,由于此接口是通过模板完成的,因此它是编译时间的,而不是run-run-时间。

要实现std :: char_traits,您根本无法使用不同的名称(至少没有basic_string的大量磨损),这些名称是接口的一部分。