1

私の卒業論文では、有限要素コードをプログラミングしています。より正確には、教員が提供する 2 つのクラス ライブラリに基づく既存のプログラムを変更しています。そのため、これらのクラスは一般的なものであるため、これらのクラスを変更することはできません。

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

それも選択肢ではありません。

最後に私の質問は次のとおりです。

変数が親クラスとして定義されているが、子クラスとしてインスタンス化されている場合、子のメソッドにアクセスするにはどうすればよいですか?

どんな助けでも本当に感謝しています。あなたの答えを前もって感謝します。

編集

参考までに、私は 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;

}
4

2 に答える 2

1

これはあなたの問題にはやり過ぎかもしれませんが、別の解決策を提示したかったのです。

オブジェクト指向プログラムでは、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;
}
于 2013-06-01T14:40:34.943 に答える
1

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
}
于 2013-06-01T13:42:32.803 に答える