跳转到内容

更多 C++ 习语/智能指针

来自维基教科书,开放的书籍,为开放的世界

智能指针

[编辑 | 编辑源代码]

句柄体 习语或信封信 习语正在使用时,减轻在句柄类中重复主体类的签名更改的负担。

也称为

[编辑 | 编辑源代码]
  • 整体委托

当使用句柄/主体习语时,可能需要在句柄类中重复主体类的接口,因为句柄由用户代码使用。这种重复通常很乏味且容易出错。智能指针习语用于减轻这种负担。智能指针习语通常与句柄类中的某种“智能”一起使用,例如引用计数、自动所有权管理等。

解决方案和示例代码

[编辑 | 编辑源代码]

根据预期的用途,至少有两种实现智能指针习语的重叠方法。

  • 完全指针语义
  • 不太像指针的语义

以上两种变体都在所谓的“句柄”类中定义了一个重载的箭头运算符。让我们从完全指针语义开始。

class Body;
class Handle // Completely pointer like semantics
{
  public:
    void set (Body *b) { body_ = b; }
    Body * operator -> () const throw()
    {
      return body_;
    }
    Body & operator * () const throw ()
    {
      return *body_;
    }
  private:
    mutable Body *body_;
};
int main (void)
{
   Handle h;
   h.set(new Body());
   h->foo();    // A way of invoking Body::foo()
   (*h).foo();  // Another way of invoking Body::foo()
}

仅使用 -> 运算符可以减轻在句柄类中重复主体类接口的问题。另一种方法是像上面代码片段中显示的那样重载解引用 (*) 运算符,但它不像前者那样自然。如果句柄抽象是某种指针抽象,那么应该提供这两个重载运算符(例如,std::auto_ptr、boost::shared_ptr)。如果句柄抽象不是指针类抽象,则不需要提供 * 运算符。相反,为常量句柄提供重载的箭头运算符集可能很有用,因为客户端始终与句柄类对象交互。对于客户端代码,句柄**就是**对象,因此句柄的常量性应该在适当的时候传播到相应的主体。通常,应该避免从常量句柄中修改非常量主体对象的不明确行为。与纯粹的指针语义不同,在某些情况下,从句柄类到主体类的自动类型转换也是可取的。

class Body;
class Handle // Less pointer like semantics
{
  public:
    void set (Body *b) { body_ = b; }
    Body * operator -> () throw()
    {
      return body_;
    }
    Body const * operator -> () const throw()
    {
      return body_;
    }
    operator const Body & () const // type conversion
    {
      return *body_;
    }
    operator Body & ()  // type conversion
    {
      return *body_;
    }
    // No operator *()
  private:
    mutable Body *body_;
};
int main (void)
{
   Handle const h;
   h.set(new Body());
   h->foo();    // compiles only if Body::foo() is a const function.
}

使用成员转换函数的另一种方法是使用非成员获取 习语,如下所示。根据接口原则,重载的非成员 get() 函数必须与句柄类位于同一个命名空间中。

namespace H {
class Body;
class Handle { ... }; // As per above.
Body const & get (Handle const &h)
{
  return *h.body_;
}
Body & get (Handle &h)
{
  return *h.body_;
}
} // end namespace H.
int main (void)
{
  H::Handle const h;
  h.set(new Body());
  get(h).foo(); // compiles only if Body::foo() is a const function.
}

已知用途

[编辑 | 编辑源代码]
  • std::auto_ptr(完全指针语义)
  • boost::shared_ptr(完全指针语义)
  • C++ 中的 CORBA Var 类型(TAO(ACE ORB)中的 TAO_Seq_Var_Base_T< T > 类 - 不太像指针的语义)
[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
华夏公益教科书