A と B を enable_shared_from_this とは少し異なるものを使用するように変更できる場合は、Potatoswatter のソリューションを拡張します。コードは標準ライブラリ バージョンを使用しますが、boost の実装は類似している必要があります。以下の説明
#include <memory>
template<typename T>
struct enable_shared_from_this_virtual;
class enable_shared_from_this_virtual_base : public std::enable_shared_from_this<enable_shared_from_this_virtual_base>
{
typedef std::enable_shared_from_this<enable_shared_from_this_virtual_base> base_type;
template<typename T>
friend struct enable_shared_from_this_virtual;
std::shared_ptr<enable_shared_from_this_virtual_base> shared_from_this()
{
return base_type::shared_from_this();
}
std::shared_ptr<enable_shared_from_this_virtual_base const> shared_from_this() const
{
return base_type::shared_from_this();
}
};
template<typename T>
struct enable_shared_from_this_virtual: virtual enable_shared_from_this_virtual_base
{
typedef enable_shared_from_this_virtual_base base_type;
public:
std::shared_ptr<T> shared_from_this()
{
std::shared_ptr<T> result(base_type::shared_from_this(), static_cast<T*>(this));
return result;
}
std::shared_ptr<T const> shared_from_this() const
{
std::shared_ptr<T const> result(base_type::shared_from_this(), static_cast<T const*>(this));
return result;
}
};
したがって、意図は、struct A
が からパブリックに継承し、 からenable_shared_from_this_virtual<A>
パブリックstruct B
に継承することenable_shared_from_this_virtual<B>
です。どちらも同じ共通の仮想オブジェクトを共有しているためstd::enable_shared_from_this
、階層には 1 つしかありません。
いずれかの classes を呼び出すと、から T* へshared_from_this
のキャストが実行されenable_shared_from_this_virtual<T>*
、shared_ptr のエイリアシング コンストラクターが使用されるため、新しい shared_ptr は T* を指し、単一の共有ポインターと所有権を共有します。
上部のフレンドの使用は、誰もが仮想ベースの shared_from_this() メンバーに直接アクセスできないようにすることです。によって提供されるものを通過する必要がありますenable_shared_from_this_virtual<T>
。
例:
#include <iostream>
struct A : public enable_shared_from_this_virtual<A>
{
void foo()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct B : public enable_shared_from_this_virtual<B>
{
void bar()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct D: A, B {};
int main()
{
std::shared_ptr<D> d(new D);
d->foo();
d->bar();
return 0;
}