7

を使用して、私たちが触れることができない、いくつかの(レガシー)コードを、仮定してみましょう姉妹継承

struct B{ 
public: 
    void f(){} 
}; 

を宣言し、私たちは

struct A{ 
public: 
    virtual void f()=0; 
}; 

は、サブクラスの呼び出しを行うことが可能である持っていると仮定してみましょうB ::明示的にFを呼び出すことなく、F()、つまり代わりに

struct C: public A, public B{ 
    void f(){ 
    B::f(); 
    } 
}; 

のようなものを持ちます
struct C:virtual public A,virtual public B{ 

}; 

(コンパイラAのために、この最後のクラスが抽象的であることに注意してください:: fが定義されていない)

+2

'B :: f()'の何が問題なのですか?それは 'B :: f()'を呼び出す正しい方法です。 –

+0

あなたは100個の関数を持っていると想像してください;) –

+2

いいえ、基本メンバ関数が別の基本クラスの純粋仮想関数を実装することはできません。それだけでは機能しません。あなたが持っているものは大丈夫です。 –

答えて

1

C++で直接、Bの関数とAの暗黙的なマッチングに基づいて多態的にディスパッチすることは不可能です。 gccxmlや他の同様の製品を使って何らかのコード生成に頼ることもできますが、100個の関数しかなければ、マクロは1ライナーへの転送を減らすことができます。これらを行う。

+0

"シグネチャを使用したタイプ抽象化"(http://gcc.gnu.org/onlinedocs/gcc-2.95) "_シグネチャ"をサポートするために、G's _used_へのBの関数の暗黙の照合に基づいた_dispatch .3/gcc_5.html#SEC112) "GNU C++では、シグネチャキーワードを使用して完全抽象クラスインタフェースをデータ型として定義することができ、シグネチャポインタを使用してこの抽象クラスを実際のクラスと関連付けることができます。 (...)シグネチャを使用すると、既存のクラス階層をシグネチャタイプの実装として扱うことができます。 – curiousguy

+0

@curiousguy:これは一般的なものです(歴史的にgcc 3で削除されています)。しかし、私は、質問が求めるものやもっと一般的には "Bの関数の暗黙のマッチングに基づいたポリモーフィックなディスパッチAの "あなたが引用します。与えられた 'シグネチャS {void f(); }; ... S * p = static_cast (this); p-> f(); 'は関数' 'std :: function x = std :: bind(&B :: f、this)と機能的に同じです。 x(); ' - どちらも、質問のように' B :: f(); 'を呼び出すだけでは不器用に思えます。私が何かを見逃しているかどうかわからない...? –

0

あなたが何か行うことができます:

void C::f() { 
    B* b = this; 
    b->f(); 
} 
+0

ありがとうございますが、私は各機能の実装を書いていません(さらに、私が書いたものに比べてこのバージョンの利点は何ですか?) –

+0

@FabioDallaLibera:わかりません。 'C'に' f'という関数を書きたくないのなら、なぜそのような関数を宣言していますか?この 'C :: f'の実装と、この場合はあなたが避けたい' B :: f'を使用しない以外の違いはありません。 –

0

ありませんが、あなたが行うことはできませんそれ。また、スニペットから、Bのメンバーは、継承ではなく構成によってCのメンバーになるように見えます。いくつかの転送機能(または自動的にそれらを生成するためのスクリプト)を書くだけでよいでしょう。

1

BAたデリゲートの実装を行います。

class A_Impl : public A 
{ 
public: 
    virtual void f() 
    { 
     b.f(); 
    } 
private: 
    B b; 
} 

A_Implから派生させることによってCを実装します。

class C: public A_Impl 
{ 
}; 

それとも、あなたが唯一の継承階層にAを表示したい場合は、導出公的にAから、私的にはA_Implから:

class C: public A, private virtual A_Impl 
{ 
}; 
-1

したがって、Aには100個の純粋仮想関数があり、それらの関数はBで実装されています。これらの関数をすべてC言語で再実装してBを呼び出すことは避けたいと思います。 Bの実装は自動的に行われます。コンパイラと戦う代わりに(毎回失うことになります)、の継承グラフを再考します。おそらくBをAのサブクラスにしてからCをBから派生させるか、Bの100個のメソッドをAの具象サブクラスに分解します。

プログラミングは、ツールによって提供される制約内で問題を解決する技術です。あなたがあなたのツールと不安を感じるときは、問題へのアプローチを考え直すか、別のツールを使用する必要があります。

+0

Bは触れることができないので、Aのサブクラスにすることはできず、メソッドをそこから移動することはできません。 – Karu