在C+中隐藏静态成员函数的名称+;:良好做法? 在我作为C++程序员的时候,我通常认为应该避免使用名字隐藏,因为它可能会导致混乱。例如,如果您有一个带有函数f()的基类和一个带有函数f()的派生类,并且f()不是虚拟的,则调用方可能会意外调用错误的f() 然而,我在阅读Head萨特的特殊C++书时遇到了一个例子,其中一个名字隐藏的案例似乎被鼓励。为了生成不区分大小写的字符串,他建议我们创建一个继承自char\u traits(非多态静态类)的char\u traits类,从而生成一个不区分大小写的std::basic\u string,如下所示: struct ci\u char\u traits:public char\u traits { 静态布尔等式(字符c1,字符c2){/*…*/} 静态布尔lt(字符c1,字符c2){/*…*/} 静态整数比较(常量字符*s1, 常量字符*s2, 大小(n){/*…*/} 静态常量字符* 查找(常量字符*s,int n,字符a){/*…*/} }

在C+中隐藏静态成员函数的名称+;:良好做法? 在我作为C++程序员的时候,我通常认为应该避免使用名字隐藏,因为它可能会导致混乱。例如,如果您有一个带有函数f()的基类和一个带有函数f()的派生类,并且f()不是虚拟的,则调用方可能会意外调用错误的f() 然而,我在阅读Head萨特的特殊C++书时遇到了一个例子,其中一个名字隐藏的案例似乎被鼓励。为了生成不区分大小写的字符串,他建议我们创建一个继承自char\u traits(非多态静态类)的char\u traits类,从而生成一个不区分大小写的std::basic\u string,如下所示: struct ci\u char\u traits:public char\u traits { 静态布尔等式(字符c1,字符c2){/*…*/} 静态布尔lt(字符c1,字符c2){/*…*/} 静态整数比较(常量字符*s1, 常量字符*s2, 大小(n){/*…*/} 静态常量字符* 查找(常量字符*s,int n,字符a){/*…*/} },c++,inheritance,C++,Inheritance,(为了更简洁,我省略了函数定义)。本质上,我们继承了char\u traits的所有函数,并且隐藏了我们想要修改的函数,以使其不区分大小写。然后,定义不区分大小写的字符串,如下所示: typedef basic_string<char, ci_char_traits> ci_string; typedef基本字符串ci字符串; 现在我确实认为这是一个相当巧妙的把戏!但我想知道这种事情是否被视为“良好做法”,因为隐藏姓名通常是不受欢迎的。也许命名隐藏静态成员函数比命名其他类型的函数

(为了更简洁,我省略了函数定义)。本质上,我们继承了
char\u traits
的所有函数,并且隐藏了我们想要修改的函数,以使其不区分大小写。然后,定义不区分大小写的字符串,如下所示:

typedef basic_string<char, ci_char_traits> ci_string;
typedef基本字符串ci字符串;

现在我确实认为这是一个相当巧妙的把戏!但我想知道这种事情是否被视为“良好做法”,因为隐藏姓名通常是不受欢迎的。也许命名隐藏静态成员函数比命名其他类型的函数更容易接受?

这里的区别在于traits类不是多态的,因此不会对使用哪个接口产生任何混淆

ci\u char\u traits
当然可以通过私有继承、封装或简单地遵从
std::char\u traits
来实现。所有这些方法都需要更多的维护

更新: 关于模板是否是多态的,在评论中有一些讨论。我将详细说明

构造
std::basic_string
导致模板
std::basic_string
的模板扩展。在此扩展过程中,进行了以下类型替换:

  • 图表
    替换为
    字符
  • Traits
    替换为
    ci\u char\u Traits
  • Allocator
    替换为
    std::Allocator
因此,编译器生成的类是:

std::基本字符串

这不是多态类

这个类将有一个名为
std::basic\u string::traits\u type
的成员typedef,它无疑是
ci\u char\u traits
类型

因此,此模板扩展将产生一个非多态类,该类使用非多态类
ci_char_traits
来确定基于字符的操作(如比较)的行为


std::basic_string
中的代码将调用
eq
lt
的哪个重载是精确定义的,这就是为什么在这种情况下,重载这些静态成员函数并不是不好的做法。

在不区分大小写的示例中,更重要的是实现一个接口,由于这个接口是通过模板完成的,所以它只是编译时的问题,而不是运行时的问题


要实现std::char\u traits,您不能使用不同的名称(至少不需要大量修改基本字符串),这些名称是接口的一部分。

它不是运行时多态的。它是编译时多态的@在我看来,“编译时多态性”是一种矛盾修饰法。它没有“多边形”。编译器选择您在
std::string
的模板参数列表中指定的指定类型。您可以传入任何符合条件的类型。@StoryTeller模板不是代码。它们是一种代码编写服务。一个模板可以生成无限多个类。这可以解释为“多边形”。但单词的第二部分是“morph”,意思是“change”。一旦模板扩展编写了我们的类,它就被修复了。因此不是“多态的”。可能有一个词,但“多态性”是错误的,它给初学者带来了错误的想法,这一问题就证明了这一点。@RichardHodges:Turing complete是另一回事。另一种方法是从头开始实现
ci\u char\u traits
,这将导致代码重复。从技术上讲,您也可以转发给私人成员。但这允许空基类优化。
typedef basic_string<char, ci_char_traits> ci_string;