2012-09-07 214 views
4

在C++ primer 15.8中,當作者談論'句柄類和繼承'時,他說:在C++中處理類?

'C++中常見的技術是定義一個所謂的覆蓋或句柄類。句柄類存儲和管理指向基類的指針。該指針指向的對象的類型將有所不同;它可以指向基類或派生類型的對象。用戶通過句柄訪問繼承層次結構的操作。由於句柄使用其指針來執行這些操作,因此虛擬成員的行爲在運行時會有所不同,具體取決於句柄實際綁定到的對象的類型。句柄的用戶因此獲得動態行爲,但本身不必擔心管理指針。

以上聽起來很像一個智能指針給我。但是,這個'處理'的用法有一點不同。

Handle h(Derived()); // noticed a derived object, not a pointer is used to initialize the handle! 
h->func(); 

和後實現手柄(如下圖所示)的證明了我把手上的筆者點評:我們想」我們的手柄來創建自己的對象的用戶,他們可以附加手柄。 手柄將分配適當類型的新對象,並複製用戶的對象成新分配的對象。這樣,手柄類將擁有該對象,可以保證對象不會被刪除,直到附着在物體上的最後一個句柄消失。」

public: 
    Base(){} 
    virtual int func(std::size_t n) const {} 
    virtual Base* clone() const { return new Base(*this); } 
}; 

class Derived : public Base { 
public: 
    Derived():Base(){} 
    int func(std::size_t) const; // redefine 
    Derived* clone() const { return new Derived(*this); } 
}; 

class Handle { 
public: 
    Handle(const Base &b):p(b.clone()), use(new std::size_t(1)) { } 
private: 
    Base *p; 
    std::size_t *use; // pointer to shared use count 
}; 

我的問題是:這真的是C++或OO中句柄的典型含義嗎?我認爲這個句柄可以只是一個基本類型的智能指針,它在內部保留use-count,或者更普遍的是一些神奇的int類型,系統知道它指向什麼以及如何處理它。爲什麼這裏的句柄需要將用戶對象拷貝到自身,然後根據拷貝進行使用計數?

任何人都可以幫助?

感謝,

回答

4

在現代C++的慣用等效是:

std::shared_ptr<Base> h{std::make_shared<Derived>()}; 

一般來說,「處理」意味着某種形式的類型擦除,使代碼處理句柄不需要知道功能如何實現的細節。

的原因,你已經證明使用clone複製對象的代碼正是爲了執行類型擦除;在clone方法被調用的時候,Derived對象的實際類型的知識被刪除。就實現質量而言,代碼是非線程安全的,這與傳統C++無關,但是對於具有線程感知內存模型的現代C++來說是個問題。它也並不明顯是異常安全的;將例外安全委派給標準庫類如shared_ptr要好得多。最後,Base類缺少虛擬析構函數。

+0

謝謝,ecatmur。我的問題更多地涉及爲什麼COPY的對象(存儲在Base * p中)完全需要。爲什麼不能讓句柄接受從'new'返回的基指針,就像智能​​指針會做的一樣,並且只跟蹤use-count。我理解'克隆'就像一個獨立於類型的虛擬構造函數。 – user1559625

+0

@ user1559625'clone'有一些開銷,但比傳遞原始分配的指針更安全。 'shared_ptr'使用'make_shared'來避免原始分配的指針,但它只能在C++ 11(它使用右值引用的完美轉發和可變參數模板)之後纔可行。 – ecatmur