2017-07-03 22 views
0

どのように私はdamamcally形式の関数を呼び出すことができます:childA.function(childB)その静的型は両方の親ですが?ポリモフィズム引数を使用して動的に関数を呼び出す方法

、より詳細で:

私は2つの分子の可能性を計算する必要がある物理学のプロジェクトを持っています。 しかし、私は2種類の分子、LCとColを持っていますが、それぞれのタイプには独自のパラメータとものがありますが、各分子の能力を動的に呼び出せるようにしたいと考えています。

ので、私はこの試みた:

#include <iostream> 
#include <typeinfo> 
#include <stdio.h> 

using namespace std; 
class Col; 
class LC; 

class Molecule 
{ 
    public: 
    /// more data and functions should be here regarding the molecule 
    double someBulshit; 
    virtual double potential(const Molecule * mol){} 
    virtual double potential(const Col * mol){} 
    virtual double potential(const LC * mol){} 
}; 

class LC : public Molecule 
{ 
    public: 
    /// more data and functions should be here regarding the LC molecule 
    virtual double potential(const Molecule * mol) {return 1;} 
    virtual double potential(const LC * mol) {return 2;} 
    virtual double potential(const Col * mol) {return 3;} 
}; 
class Col : public Molecule 
{ 
    public: 
    /// more data and function should be here regarding the Col molecule 
    virtual double potential(const Molecule * mol) {return 4;} 
    virtual double potential(const LC * mol) {return 5;} 
    virtual double potential(const Col * mol) {return 6;} 
}; 

int main(int argc, char* argv[]) 
{ 
    Molecule * mol1 = new Col(); 
    Molecule * mol2 = new LC(); 

    double my_potential = mol1->potential(mol2); 
    printf ("%f",my_potential); 
} 

をしかし、それはmol1の静的な型が分子であるため、呼び出された関数であることを意味し、関数は、スタティックにコールされていることが判明したとして、私は、4の結果が得られます。

virtual double potential(const Molecule * mol) {return 4;} 

なく

virtual double potential(const LC * mol) {return 5;} 

は、関数DYNAを呼び出すことがとにかくありそれにtypeidを使用しないでmically(OOPデザインで)?

フル答え:

#include <iostream> 
#include <typeinfo> 
#include <stdio.h> 


using namespace std; 
class Col; 
class LC; 

class Molecule 
{ 
    public: 
    /// more data and functions should be here regarding the molecule 
    double someBulshit; 
    virtual double potential(const Molecule * mol) const = 0; 
    virtual double potential(const Col * mol) const = 0; 
    virtual double potential(const LC * mol) const = 0; 
}; 

class LC : public Molecule 
{ 
    public: 
    /// more data and functions should be here regarding the LC molecule 
    virtual double potential(const Molecule * mol) const {return mol->potential(this);} 
    virtual double potential(const LC * mol) const {return 2;} 
    virtual double potential(const Col * mol) const {return 3;} 
}; 
class Col : public Molecule 
{ 
    public: 
    /// more data and function should be here regarding the Col molecule 
    virtual double potential(const Molecule * mol) const {return mol->potential(this);} 
    virtual double potential(const LC * mol) const {return 5;} 
    virtual double potential(const Col * mol) const {return 6;} 
}; 

int main(int argc, char* argv[]) 
{ 
    Molecule * mol1 = new Col(); 
    Molecule * mol2 = new LC(); 

    double my_potential = mol1->potential(mol2); 
    printf ("%f",my_potential); 
} 

ピーターのアドバイスと調査の後、これは完全な解決策は、ちょうどこのように仮想内の別の仮想を呼び出すことで、古典的な二重派遣の問題であることが判明

これは実際に必要に応じて3を返します。

+0

あなたのソースコードがコンパイルされません。その犯人は、「分子」のメンバー関数です。 'Molecule'データメンバの名前を変更することもできます。多分あなたはそれらの純粋な仮想を作ることを忘れましたか?関数は静的に_呼び出されません_。 [MCVE](https://stackoverflow.com/help/mcve)を入力してください。 – Ron

+1

訪問者パターンを調べます。 – Peter

答えて

1

あなたが渡す引数の型であるため、あなたは常にpotential(Molecule *)を呼び出しています。

動的に実行する(実行時の決定を行う)場合は、動的にキャストして、どのタイプのものを使用しているのかを判断し、適切な関数を呼び出す必要があります。たとえば、実際の型をチェックして、正しい型のオーバーロードされた関数を呼び出します。コードは次のようになります。

#include <iostream> 
#include <typeinfo> 
#include <stdio.h> 

using namespace std; 
class Col; 
class LC; 

class Molecule 
{ 
    public: 
    virtual ~Molecule() {} 
    /// more data and functions should be here regarding the molecule 
    double someBulshit; 
    double potential(const Molecule * mol); 
    virtual double potential(const Col * mol) = 0; 
    virtual double potential(const LC * mol) = 0; 
}; 

class LC : public Molecule 
{ 
    public: 
    virtual ~LC() {} 
    /// more data and functions should be here regarding the LC molecule 
    virtual double potential(const LC * mol) {return 2;} 
    virtual double potential(const Col * mol) {return 3;} 
}; 
class Col : public Molecule 
{ 
    public: 
    virtual ~Col() {} 
    /// more data and function should be here regarding the Col molecule 
    virtual double potential(const LC * mol) {return 5;} 
    virtual double potential(const Col * mol) {return 6;} 
}; 

double Molecule::potential(const Molecule * mol) { 
    const Col *mol_as_Col = dynamic_cast<const Col*>(mol); 
    const LC *mol_as_LC = dynamic_cast<const LC*>(mol); 
    if(mol_as_Col) { 
    return potential(mol_as_Col); 
    } 
    else if(mol_as_LC) { 
    return potential(mol_as_LC); 
    } 
    else { 
    throw; 
    } 
} 


int main(int argc, char* argv[]) 
{ 
    Molecule * mol1 = new Col(); 
    Molecule * mol2 = new LC(); 

    double my_potential = mol1->potential(mol2); 
    printf ("%f",my_potential); 
} 

結果は5になり、6あなたは型LCに入れ、大佐に電話をかけるため、あなたは、あなたの質問に書いたように、私も不足しているが追加されていませんポリモーフィックなクラスは常にそれを持つ必要があるので、仮想デストラクタ。

また、これをテンプレートコードで実装して、実行時の多態性を最初に使用しないようにすることもできます(つまり、分子型*のポインタは決して保持しないでください)。興味があれば、私は例を試すことができますが、具体的にはダイナミックなソリューションを求めているので、この質問に対する答えとは思われません。

EDIT:テンプレートデモンストレーションの後です。文脈がなければ本当に意味をなさない。これを書いている間、私は第三(と実際優先)方法があるかもしれないと思う、実際に

#include <iostream> 
#include <typeinfo> 
#include <stdio.h> 

using namespace std; 

template<typename MOLECULE1, typename MOLECULE2> 
void printPotential(MOLECULE1 *mol1, MOLECULE2 *mol2) { 
    double my_potential = mol1->potential(mol2); 
    printf("%f",my_potential); 
} 

class Col; 

class LC 
{ 
    public: 
    /// more data and functions should be here regarding the LC molecule 
    double potential(const LC * mol) {return 2;} 
    double potential(const Col * mol) {return 3;} 
}; 
class Col 
{ 
    public: 
    /// more data and function should be here regarding the Col molecule 
    double potential(const LC * mol) {return 5;} 
    double potential(const Col * mol) {return 6;} 
}; 


int main(int argc, char* argv[]) 
{ 
    Col *mol1 = new Col(); 
    LC *mol2 = new LC(); 

    printPotential(mol1, mol2); 
} 

:あなたが見つける必要がある私はあなたのコードの残りの部分を書きます方法を示して機能printPotential()を追加しました基底クラスの一部である(または基底クラスの仮想関数呼び出しによって得られる)共通情報のみを使用することによって、2つの分子間のポテンシャルをどのように計算するかを抽象化したアルゴリズムです。その場合、potential()の1つの実装(Molecule *型の単一引数を持つ基本クラスのメンバ関数として、またはMolecule *型の2つの引数を持つ非メンバ関数として)を1つだけ実装できます。私は2つの分子間ポテンシャルは(ちょうどダムの例のように)2「絶対」ポテンシャルの違いであると仮定した場合、それは次のようになります。

#include <iostream> 
#include <typeinfo> 
#include <stdio.h> 

using namespace std; 
class Col; 
class LC; 

class Molecule 
{ 
    public: 
    virtual ~Molecule() {} 
    /// more data and functions should be here regarding the molecule 
    double potential(const Molecule * mol) { 
    return mol->getAbsolutePotential() - getAbsolutePotential(); 
    } 
    virtual double getAbsolutePotential() const = 0; 
}; 

class LC : public Molecule 
{ 
    public: 
    virtual ~LC() {} 
    /// more data and functions should be here regarding the LC molecule 
    double getAbsolutePotential() const {return 42.0;} 
}; 
class Col : public Molecule 
{ 
    public: 
    virtual ~Col() {} 
    /// more data and function should be here regarding the Col molecule 
    double getAbsolutePotential() const {return 120.0;} 
}; 


int main(int argc, char* argv[]) 
{ 
    Molecule * mol1 = new Col(); 
    Molecule * mol2 = new LC(); 

    double my_potential = mol1->potential(mol2); 
    printf ("%f",my_potential); 
} 
+0

私はダイナミックなソリューションはよりOOPのようなデザインだと思った。 テンプレートがここに適していると思うなら、私はそのような解決策を見てうれしく思います。私はまた、リターン6の間違いを修正しました。 – pio

+1

私の答えの編集を参照してください:-) –

関連する問題