この投稿は数年前のものですが、何か役立つものを追加できるかもしれません。元の投稿のクラスのデザインはそれほど見栄えが良くないと言いますが、埋め込まれたクラスが含まれているクラスにアクセスできるようにすると便利な場合があります。これは、余分なポインタを格納せずに簡単に実行できます。以下に例を示します。いくつかの既存のコードからそれを取り、いくつかの名前を変更したので、それは機能するはずです。重要なのはEmbeddorOfマクロです。チャームのように機能します。
////////////////////.hファイル/////////////////////////
struct IReferenceCounted
{
virtual unsigned long AddRef() = 0;
virtual unsigned long Release() = 0;
};
struct IFoo : public IReferenceCounted
{
};
class Foo : public IFoo
{
public:
static IFoo* Create();
static IFoo* Create(IReferenceCounted* outer, IReferenceCounted** inner);
private:
Foo();
Foo(IReferenceCounted* outer);
~Foo();
// IReferenceCounted
unsigned long AddRef();
unsigned long Release();
private:
struct EIReferenceCounted : IReferenceCounted
{
// IReferenceCounted
unsigned long AddRef();
unsigned long Release();
} _inner;
unsigned long _refs;
IReferenceCounted* _outer;
};
////////////////.cppファイル/////////////////
#include <stdio.h>
#include <stddef.h>
#include "Foo.h"
#define EmbeddorOf(class, member, this) \
(class *) ((char *) this - offsetof(class, member))
// Foo
Foo::Foo() : _refs(1), _outer(&this->_inner)
{
}
Foo::Foo(IReferenceCounted* outer) : _refs(1), _outer(outer)
{
}
Foo::~Foo()
{
printf("Foo::~Foo()\n");
}
IFoo* Foo::Create()
{
return new Foo();
}
IFoo* Foo::Create(IReferenceCounted* outer, IReferenceCounted** inner)
{
Foo* foo = new Foo(outer);
*inner = &foo->_inner;
return (IFoo*) foo;
}
// IReferenceCounted
unsigned long Foo::AddRef()
{
printf("Foo::AddRef()\n");
return this->_outer->AddRef();
}
unsigned long Foo::Release()
{
printf("Foo::Release()\n");
return this->_outer->Release();
}
// Inner IReferenceCounted
unsigned long Foo::EIReferenceCounted::AddRef()
{
Foo* pThis = EmbeddorOf(Foo, _inner, this);
return ++pThis->_refs;
}
unsigned long Foo::EIReferenceCounted::Release()
{
Foo* pThis = EmbeddorOf(Foo, _inner, this);
unsigned long refs = --pThis->_refs;
if (refs == 0)
{
// Artifically increment so that we won't try to destroy multiple
// times in the event that our destructor causes AddRef()'s or
// Releases().
pThis->_refs = 1;
delete pThis;
}
return refs;
}
ニック