簡體   English   中英

通過繼承擴展 shared_ptr

[英]extending shared_ptr by inheritance

做這樣的事情有什么不好?

class myclass : public std::shared_ptr<myotherclass> {
     // some code,  an allocation is never done
     std::string get_info () {
          if(*this != nullptr) return "<info>" + (this->info * 3) + "</info>";
          else return "";
     }
 };

當類中沒有分配時——只是提供一些像上面那樣的裝飾?

原則上允許從 STL 類派生,請參閱此處此處 但是,您必須注意,您不應該使用指向基類的指針——即在這種情況下是std::shared_ptr<myotherclass>*

因此,應禁止此及其變體:

std::shared_ptr<myotherclass>* ptr = new myclass(/* ... */);

...但同意,這看起來有點合成。

為什么被禁止? 因為 STL 類沒有虛擬析構函數。 所以當你想delete你分配的類時,派生部分仍然存在。 這反過來會調用未定義的行為並可能造成內存泄漏——即使您在派生類中沒有一些分配。

為此,一種可能性是從shared_ptr私下派生:

class myclass : private std::shared_ptr<myotherclass> {};
                ^^^^^^^

但是,這可能會帶來二進制兼容性問題,請參閱對此答案的評論。

另一方面,即使前者是允許的,您也可以繼續減少出錯的可能性,或者使用組合,將shared_ptr myclass的成員並公開所需的功能(缺點是有時必須公開很多)。 或者你可以設置一個獨立的函數來做你想要的......我知道你知道;-)

由於您永遠不會手動delete它(並且您永遠不應該手動delete任何內容,這首先是shared_ptr的重點),因此虛擬析構函數並不是真正的問題。

不過,可能會出現一些互操作性問題。

  1. 只有在創建派生類的特定實例時才能獲得派生類。 當您從諸如get_shared_from_this地方獲得shared_ptr ,它不會包含您的info

  2. shared_ptr<T>上重載的函數模板不會看到繼承。 您的派生類將突然出現在隨機函數(例如std::static_pointer_cast

幸運的是,C++ 標准庫充滿了簡潔的可擴展性鈎子。 您可以像這樣安裝自定義刪除器:

template< typename t >
struct my_deleter
    : std::default_delete< t > {
    std::string info;

    my_deleter( std::string in_info )
        : info( std::move( in_info ) ) {}
};

std::shared_pointer< foo > myfoo( new foo, my_deleter{ "it's a foo" } );

並使用非成員函數檢索信息:

template< typename t >
std::string get_my_info( std::shared_ptr< t > ptr ) {
    my_deleter< t > * dp = std::get_deleter< my_deleter< t > >( ptr );
    if ( ! dp ) return {};
    return dp->info;
}

這不是一個很好的程序架構,因為每個共享對象只有一個自定義刪除器槽。 不過,它可以在緊要關頭做到。

我建議使用std::enable_shared_from_this<>然后this->shared_from_this() std::enable_shared_from_this<> this->shared_from_this()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM