无法实例化标准方面

时间:2017-12-27 13:03:52

标签: c++

当然,实例化一个方面是不可能的,因为方面不会封装任何特定的功能,而是将其留给从facet派生的特定类,例如整理等。

即,facet类被设计为基类。

出于这个原因,为了防止facet被直接实例化,它的构造函数受到保护,析构函数是虚拟的(以确保正确销毁派生类对象):

class locale::facet
{
protected:
   explicit facet(size_t refs = 0);

   virtual ~facet();

   facet(const facet&) = delete;
   void operator=(const facet&) = delete;
};

但是,现在考虑标准的facet collat​​e,它来自facet:

template<typename C>
class collate : public locale::facet
{
public:
   /// ...

protected:
   ~collate();      /// note: protected destructor

   virtual int do_compare(
                  const C* b, const C* e,
                  const C* b2, const C* e2) const;

   virtual string_type do_transform(
                          const C* b,
                          const C* e) const;

   virtual long do_hash(const C* b,
                        const C* e) const;
};

请注意,析构函数也受到保护。因此,您无法实例化整理。如果您尝试这样做,您将收到错误:

collate<char> colc;

错误是:

error: 'std::collate<_CharT>::~collate() [with _CharT = char]' is protected|

然而,整理模板类的受保护成员(do_compare(),do_transform()和do_hash())都包含封装的功能,并且不需要使用受保护的dtor声明标准的facet collat​​e

出于这个原因,要创建一个整理,我们需要首先从collat​​e派生一个类,然后可以实例化它!

template<typename C>
class My_collate : public collate<C>
{
public:
    explicit My_collate(size_t r = 0) :
        collate<C> {r}
    {
    }
};

My_collate<char> mcolc;

这成功地创建了一个My_collat​​e(通过派生来整理)。

为了证明My_collat​​e封装了继承的功能,我已经成功测试了它:

void print(const string& s1, const string& s2,
           const int& rslt)
{
    string srslt {};

    switch(rslt)
    {
    case 0:
        srslt = "equal";
        break;

    case 1:
        srslt = "s1 > s2";
        break;


    case -1:
        srslt = "s1 < s2";
        break;
    }

    cout << "comparison of " << s1 << " and " << s2
         << " using the mcolc facet : "
         << srslt << endl;
}


void test(const string& s1, const string& s2)
{
    /// since compare() operates on char[]s
    const char* s1b = s1.data();        /// start of data
    const char* s1e = s1b + s1.size();  /// end of data
    const char* s2b = s2.data();        /// start of data
    const char* s2e = s2b + s2.size();  /// end of data

    int rslt = mcolc.compare(s1b, s1e, s2b, s2e);

    /// display results
    print(s1, s2, rslt);
}


int main()
{
    test("Hello", "Hello");
    test("Hello", "hello");
    test("hello", "Hello");
}

https://ideone.com/D6zrbr

这是输出:

comparison of Hello and Hello using the mcolc facet : equal
comparison of Hello and hello using the mcolc facet : s1 < s2
comparison of hello and Hello using the mcolc facet : s1 > s2

所以,我的问题是:为什么像collat​​e这样的标准方面有一个受保护的析构函数,以便在它们已经封装完整的所需功能时阻止直接实例化?

感谢。

1 个答案:

答案 0 :(得分:0)

我已在another forum上发布此查询。

根据回复,似乎这个动作是C ++标准制定者的故意,以防止新手实例化标准库方面,例如整理。

毕竟,正如Stroustrup所述[&#34; The C ++ Programming Language&#34;,4th Ed,pg 1125],

It is essential for one to have a detailed knowledge of individual facets, 
to be able to successfully mix and match facets or add new versions of 
the standard facets.