2017-07-03 67 views
0

如何可以調用形式爲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); 
} 

,但我得到的4結果,事實證明該函數是靜態調用,這意味着,由於靜態類型mol1的是分子調用的函數爲:

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

,而不是

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

反正是有調用函數DYNA mically(在OOP設計中)不使用typeid?

完整的答案:

與彼得的意見調查後,這變成是經典的雙調度問題的全面解決方案只是調用另一個虛擬的虛擬裏面是這樣的:

#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」數據成員。也許你忘了做這些純粹的虛擬?函數不是staticly_。請提供[MCVE](https://stackoverflow.com/help/mcve)。 – Ron

+1

查看訪客模式。 – Peter

回答

1

您總是調用潛在的(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,並就西電話我也開始加入失蹤虛擬析構函數,因爲多態類應該總是有它。

或者,您可以嘗試使用模板代碼實現此功能,並避免首先使用運行時多態性(即從不保持類型Molecule *的指針)。如果你有興趣,我可以制定一個例子,但是因爲你特別要求一個動態的解決方案,它似乎不是這個問題的答案。

編輯:下面是一個模板演示。沒有上下文就沒有意義。我添加了一個功能printPotential(),它演示瞭如何編寫代碼的其餘部分:

#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); 
} 

其實,在寫這個我覺得可能是第三個(實際上是推薦)方法:你需要找到一個抽象算法如何通過僅使用可以是基類的一部分的公共信息(或通過基類的虛函數調用而獲得)來計算兩個分子之間的勢能。在這種情況下,您可以只有一個潛在的實現()(或者作爲基類的成員函數,帶有Molecule *類型的單個參數,或者作爲具有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 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

我認爲動態解決方案更像面向對象設計。 如果您認爲模板更適合這裏,我會很高興看到這種解決方案。我也修正了返回6的錯誤,thx! – pio

+1

查看我的答案編輯:-) –