2013-06-01 303 views
0

對於我的畢業論文,我正在編寫一些有限元代碼,或者更準確地說,我正在修改一個現有的程序,它基於2個類庫我的教師。因此,我無法修改這些類,因爲這些類是普遍的。C++:error:'class'沒有名字的成員

我創建了一個類BurgersMSrc,它從父類ValSrc繼承。我用一種方法calcFourierCoefficient擴大了孩子班級。在編譯的時候我收到以下錯誤:

burgers1d.cpp:268:12: error: ‘class ValSrc’ has no member named ‘calcFourierCoefficient’ 

這是有道理的,因爲變量定義爲:

ValSrc* srcTerm; 

不具有定義的方法。後來該變量的實例化依賴於問題類型,其中被實例化爲任

srcTerm = new ConstVS(f); 

srcTerm = new BurgersMSrc(prm); 

。有條件地限定srcTerm如任一ConstVSBurgersMSrc對象收率:

error: ‘srcTerm’ was not declared in this scope 

即不是一種選擇任一。

所以最後我的問題是:

If a variable is defined as a parent class, but instantiated as a child class, how do I access the child's method(s)?

任何幫助真的讚賞,並提前爲您解答感謝。

編輯

通知你,我不是很用C++經驗,但我有在C#和VBA編程的經驗。然而,我喜歡學習,所以朝着正確的方向指針非常歡迎:)

/編輯更

相關的代碼行從頭文件:

#ifndef BurgersMSS_H 
#define BurgersMSS_H 
#include "mfem.hpp" 
#include "mex.h" 

class BurgersMSol: public ValSrc 
{ 
    ... 
}; 

class BurgersMSrc: public ValSrc 
{ 

public: 

    typedef ValSrc Super; 

    BurgersMSrc(ParamDB &prm) {init(prm);} 
    virtual void init(ParamDB &prm); 

    ~BurgersMSrc(){} 

    inline void getValues (Vector &coords, Vector &msrc){} 
    void calcFourierCoefficient(int p){} 

private: 

    double nu; 
    double Tn; 
    int prob; 
    int nTimeSteps; 
    int specModes; 
    double s_n; 
    double tT; 
    double deltaT; 
    vector <double> a_re; 
    vector <double> a_im; 
    int accuracy; 
    double randomNr; 

    double randomNumber(int p){return randomNr;} 

}; 

#endif 

從相關線在CPP文件:

#include "BurgersMSS.h" 

void BurgersMSol::init(ParamDB &prm) 
{ 
    ... 
} 

BurgersMSol::~BurgersMSol(){} 

inline void BurgersMSol::getValues (Vector &coords, Vector &msol) 
{ 
    ... 
} 

BurgersMSrc::init(ParamDB &prm) 
{ 
    Super::init(); objectName="BurgersMSrc"; 
    nu = 1.0; prm.find("nu", nu); 
    prob = 1; prm.find("problem", prob); 
    if (prob == 3) 
    { 
     ... 
     this->calcFourierCoefficient(accuracy); 
    } 
} 

BurgersMSrc::~BurgersMSrc(){} 

inline void BurgersMSrc::getValues (Vector &coords, Vector &msrc) 
{ 
    ... 
} 

void BurgersMSrc::calcFourierCoefficient(int p) 
{ 
    for(int n=0;n<specModes;n++) 
    { 
     if (time == 0) 
     { 
      a_re[n] = randomNumber(p); 
      a_im[n] = randomNumber(p); 
     } 
     else 
     { 
      a_re[n] = a_re[n]*exp(-tT) + randomNumber(p); 
      a_im[n] = a_im[n]*exp(-tT) + randomNumber(p); 
     } 
    } 
} 

double BurgersMSrc::randomNumber(int p) 
{ 
    int mod = pow(10,p);  
    int rN = -mod + rand() % (2*mod); 
    randomNr = rN/(double)mod; 
    return randomNr; 
} 

主程序的相關線路:

#include "mfem.hpp" 
#include "mex.h" 
#include "BurgersMSS.h" 
... 

int main (int argc, char *argv[]) { 
    ... 

    ValSrc *srcTerm; 
    ... 

    if (problem==1) { 
     ... srcTerm = new ConstVS(f); 
     ... 
    } else if (problem==2) { 
     ... srcTerm = new ConstVS(f); 
     ... 
    } else if (problem==3){ 
     srcTerm = new BurgersMSrc(prm); 
     ... 
    } else { 
     srcTerm = new BurgersMSrc(prm); 
     ... 
    } 

    ... 
    stiffInt->setSrc(*srcTerm); 
    ... 

    for (int step = 0; step < nTimeSteps; step ++) { 
    ... 
     if (problem == 3) 
     { 
      srcTerm->calcFourierCoefficient(accuracy); //This line throws the error 
     } 
     ... 
    } 

    ... 
    return 0; 

} 
+0

我不是很瞭解這方面的知識,但看看使用動態演員表。如果你嘗試動態地將基類轉換爲派生類,它應該拋出一個異常 – Vlad

回答

0

如果ValSrc沒有一個方法calcFourierCoefficient,那麼你就不能調用上的指針方法ValSrc。你必須轉換成適當的類型。例如:

BurgersMSrc* p = dynamic_cast<BurgersMSrc*>(srcTerm); 

if (p) 
{ 
    p->calcFourierCoefficient(accuracy); 
} else 
{ 
    // srcTerm was not pointing to an instance of the appropriate type 
} 
+0

謝謝,我會研究它! – Eswald

+0

好吧,我已經解釋了它,並且在修正了我的類文件的一些其他錯誤後,我將它運行在我的驗證程序上。 還有一個問題,這完全是由於我缺乏C++經驗和知識: 'calculateFourierCoefficient'修改'BurgersMSrc'對象的私有成員'a_re'和'a_im'。如果我執行'p-> calcFourierCoefficient(accuracy);',我認爲這會改變'srcTerm'的私有成員,因爲'p'被定義爲一個指針。它是否正確? – Eswald

+0

@Eswald否,'BurgersMSrc :: calculateFourierTransform'不能看到基類的私有成員,即使可以,類似命名的成員'BurgersMSrc'仍然會優先,無論函數如何被調用。一個函數不知道它是否被分派到一個指針,引用或對象上,並且如果它確實沒有任何區別的話。 – Oktalist

0

這可能是矯枉過正的問題,但我想提出一種替代解決方案。

在面向對象的程序中,必須使用dynamic_cast或類似的技術在運行時確定對象的類型,然後執行某種類型特定的邏輯通常被認爲是設計問題的症狀。這裏有不同的方法來處理它:

struct Problem { 
    virtual ValSrc &valSrc() = 0; 
    virtual void doStep() = 0; 

    void main(StiffInt *stiffInt); 
}; 

void Problem::main(StiffInt *stiffInt) 
{ 
    // ... 
    stiffInt->setSrc(valSrc()); 
    // ... 

    for (int step = 0; step < nTimeSteps; step ++) { 
     // ... 

     doStep(); 

     // ... 
    } 
    // ... 
} 

struct Problem1 : Problem { 
    ConstVS srcTerm; 

    Problem1(F f) : srcTerm(f) 
    { 
     // ... 
    } 

    virtual ValSrc &valSrc() { return srcTerm; } 

    virtual void doStep() 
    { 
     // ... 
    } 
}; 

struct Problem2 : Problem { 
    ConstVS srcTerm; 

    Problem2(F f) : srcTerm(f) 
    { 
     // ... 
    } 

    virtual ValSrc &valSrc() { return srcTerm; } 

    virtual void doStep() 
    { 
     // ... 
    } 
}; 

struct Problem3 : Problem { 
    BurgersMSrc srcTerm; 

    Problem3(PRM prm) : srcTerm(prm) 
    { 
     // ... 
    } 

    virtual ValSrc &valSrc() { return srcTerm; } 

    virtual void doStep() 
    { 
     srcTerm.calcFourierCoefficient(accuracy); 
    } 
}; 

struct Problem4 : Problem { 
    BurgersMSrc srcTerm; 

    Problem4(PRM prm) : srcTerm(prm) 
    { 
     // ... 
    } 

    virtual ValSrc &valSrc() { return srcTerm; } 

    virtual void doStep() 
    { 
     // ... 
    } 
}; 

int main (int argc, char *argv[]) { 
    // ... 

    if (problem==1) { 
     Problem1(f).main(stiffInt); 
    } else if (problem==2) { 
     Problem2(f).main(stiffInt); 
    } else if (problem==3){ 
     Problem3(prm).main(stiffInt); 
    } else { 
     Problem4(prm).main(stiffInt); 
    } 

    return 0; 
} 
+0

因此,如果正確解釋這個主程序的所有代碼都包含在struct'Problem'中?如果是這樣,它確實看起來有點像矯枉過正,因爲它涉及很多重寫,因爲涉及到很多其他類和對象。雖然我在這個解決方案中看到了一些優勢。我可能會與我的教授討論:)。 – Eswald

+0

@Eswald:有多種方式來組織它。在你的例子中,這似乎是一個很好的方式來構造它,因爲它也消除了動態分配ValSrc的需求,但其他細節問題可能會使其他一些結構變得更清潔。 –

相關問題