通常のひし形パターンがあるとします。
class A
{
public:
virtual char foo() = 0;
virtual ~A() {}
};
class B : public A
{
public:
virtual char foo() { return 'B';}
virtual ~B() {}
};
class C : public A
{
public:
virtual char foo() { return 'C';}
virtual ~C() {}
};
class D : public B, public C
{
public:
virtual char foo() { return 'D';}
virtual ~D() {}
};
A
基本クラスにはデータ メンバーがないことに注意してください。実際には、純粋な仮想メソッドを備えたインターフェイスにすぎません。
今私がする場合:
D* d = new D();
A* a = static_cast<A*>(d);
コンパイラは、2 つの A 基底クラスがあるため、キャストがあいまいであることを教えてくれます。
しかし、もし私がそうしたらどうしますか:
D* d = new D();
B* b = static_cast<B*>(d); // Or C* c = static_cast<C*>(d);
A* a = static_cast<A*>(b);
A
これで、基本クラスの 1 つへのポインターがあり、実行できますa->foo()
。
これは安全ですか?
私が知りたいのは、この二重アップキャストを実行して、仮想継承のオーバーヘッドなしでインターフェイスへのポインター (データメンバーなし) を持つことができるかどうかです。とにかくポインターをダウンキャストしたり、仮想メソッドを呼び出していない何かをしたりするつもりはありません。
これは 2 つの基本クラスを持つことを意味することはわかっていますが、メンバーがないので問題にならないのでしょうか。
EDIT
: インターフェイスを実装する方法を見つけるのに苦労しています。仮想継承を使用する必要があると思います。
クラスBuffer
(インターフェースクラス)と、BufferImplementation
そこから派生したクラスがあるとします。
ここで、 と インターフェイスの両方から派生する必要があるクラスを持つ別のインターフェイスIOBuffer
(他のインターフェイスから派生する) があるとします。Buffer
IOBufferImplementation
BufferImplementation
IOBuffer
前の例では、Buffer は A、BufferImplementation は B、IOBuffer は C、IOBufferImplementation は D です。