本文共 2284 字,大约阅读时间需要 7 分钟。
转载自:
所有标准库版本的locale中都必须包含某些标准的facet
除此之外,用户可以安装属于自己的facet,或者替换标准的facet我们怎么产生自己的facet呢?
任何一个类型F,只要满足一下两个条件,就可以作为facet: 1. F以public形式派生自locale::facet. facet主要定义了一些机制,共locale对象内部的引用计数器使用。 此外还将拷贝构造和拷贝复制函数声明为private, 禁止外界拷贝facet,也禁止外界对facet赋值 2. F必须拥有一个型别为locale::id的public static member,名为id. 此成员用来“以某个facet型别为索引,搜索locale之内的一个facet”下面是CodeBlocks中facet的源码(id的实现在locale中):
class locale::facet { private: friend class locale; friend class locale::_Impl; mutable _Atomic_word _M_refcount; static __c_locale _S_c_locale; static const char _S_c_name[2]; #ifdef __GTHREADS static __gthread_once_t _S_once; #endif static void _S_initialize_once(); protected: explicit facet(size_t __refs = 0) throw() : _M_refcount(__refs ? 1 : 0) { } virtual ~facet(); static void _S_create_c_locale(__c_locale& __cloc, const char* __s, __c_locale __old = 0); static __c_locale _S_clone_c_locale(__c_locale& __cloc); static void _S_destroy_c_locale(__c_locale& __cloc); static __c_locale _S_get_c_locale(); static const char* _S_get_c_name(); private: inline void _M_add_reference() const throw() { __gnu_cxx::__atomic_add(&_M_refcount, 1); }inline void _M_remove_reference() const throw()
{ if (__gnu_cxx::__exchange_and_add(&_M_refcount, -1) == 1) { try { delete this; } catch (...) { } } } ///私有的拷贝构造和拷贝复制函数 facet(const facet&); facet& operator=(const facet&); }; 标准facet不仅仅遵循上述两条机制,还遵循一些特殊原则。 如果能做到这些原则,还是好处多多。这些原则包括: 1. 所有的成员函数均声明为const. 2. 所有的public成员函数均不是虚函数,而是将调用操作委托给一个protected函数, 后者的命名类似于对应的public函数,只不过在前面家霍桑do_ 如numpunct::truename会调用numpunct::do_truename() 因此,如想改变某个facet,应该改写其对应的protected函数下面是numpunct类的源码,来源于MSDN,从中也可以看到上面说的两条原则:
template<class E>
class numpunct : public locale::facet { public: typedef E char_type; typedef basic_string<E> string_type; explicit numpunct(size_t refs = 0); E decimal_point() const; E thousands_sep() const; string grouping() const; string_type truename() const; string_type falsename() const; static locale::id id; protected: ~numpunct(); virtual E do_decimal_point() const; virtual E do_thousands_sep() const; virtual string do_grouping() const; virtual string_type do_truename() const; virtual string_type do_falsename() const; }大部分标准facet都定义了一个"_byname"版本。这个版本派生自标准的facet。 被用来根据locale名称产生出相应的facet。 如class numpunct_byname被用来针对一个有名称的locale产生一个numpunct facet