做这样的事情有什么不好?
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类派生,请参阅here和here。但是,您必须注意,不应使用指向基类的指针-在这种情况下,即为std::shared_ptr<myotherclass>*
。
因此应禁止使用此方法及其变体:
std::shared_ptr<myotherclass>* ptr = new myclass(/* ... */);
...但是同意,这看起来有点综合。
为什么禁止?因为STL类没有虚拟析构函数。因此,当您想delete
您分配的类时,派生的部分仍然保留。反过来,这会调用undefined behaviour并可能导致内存泄漏-即使您的派生类中没有一些分配。
为了这样做,一种可能性是从shared_ptr
私下获得:
class myclass : private std::shared_ptr<myotherclass> {};
^^^^^^^
但是,这可能会带来二进制兼容性的问题,请参见this answer的注释。
一方面,即使允许使用前者,也可以减少出错的可能性,并且可以使用组合,将shared_ptr
设为myclass
的成员并公开所需的功能(缺点是有时不得不暴露很多)。或者,您可以设置一个独立的函数来执行您想要的操作...我知道您知道;-)
因为您永远不会手动delete
(并且永远不要手动delete
任何东西,首先是shared_ptr
的要点,所以虚拟析构函数并不是真正的问题。
但是可能会出现一些互操作性问题。
您只有在创建派生类的特定实例时才获得它。当您从shared_ptr
之类的地方获得get_shared_from_this
时,它将不包含您的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()。