c 中的名称隐藏式成员功能:良好实践
Name-hiding static member functions in C++: good practice?
在我作为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>
的模板扩展。在此扩展过程中,进行了以下类型的替换:
-
CharT
被char
替换 -
Traits
被ci_char_traits
替换 -
Allocator
被std::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
来确定基于字符的操作的行为,例如比较。
eq
和 lt
的哪种过载可以通过类std::basic_string<char, ci_char_traits, std::allocator<char>>
中的代码调用,这就是为什么在这种情况下,超载这些静态成员函数的习惯不是不好的做法。
在不敏感的示例中,这更重要的是实现接口,这只是碰巧的是,由于此接口是通过模板完成的,因此它是编译时间的,而不是run-run-时间。
要实现std :: char_traits,您根本无法使用不同的名称(至少没有basic_string的大量磨损),这些名称是接口的一部分。
- 类模板的成员功能的定义在单独的TU中完全专业化
- 升压信号2将插槽传递到成员功能以断开连接
- 多次实现成员功能
- 如何定义可变参数类模板的成员模板功能
- 私有成员数据不可用于公共成员功能
- 好友功能 - 成员无法访问
- 如何启用友元类的友元功能直接在C++中访问其私有成员
- 无法从好友功能访问类的私有成员?"ostream"不是"std"的成员?
- C++从成员类型中扣除类型的功能模板?
- 如何避免大多数成员功能相同的代码重复
- 无法访问公共功能? 没有指定成员?
- C 成员功能
- =删除用户定义的成员功能,除了构造函数,分配运算符C 11
- C 朋友课程和朋友成员功能
- C 函数调用包装器包含类成员功能作为模板参数
- 共享库中静态功能成员的破坏顺序
- 可以使用仅功能成员属性进行回调界面
- 虚拟方法与std ::功能成员变量在性能方面
- 虚拟继承和功能成员
- 指向功能成员和非成员的指针