[英]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
的重點),因此虛擬析構函數並不是真正的問題。
不過,可能會出現一些互操作性問題。
只有在創建派生類的特定實例時才能獲得派生類。 當您從諸如get_shared_from_this
地方獲得shared_ptr
,它不會包含您的info
。
在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.