跳轉到內容

更多 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 > 類 - 不太像指標的語義)
[編輯 | 編輯原始碼]

參考資料

[編輯 | 編輯原始碼]
華夏公益教科書