2013-06-01 3 views
0

Для моей дипломной работы я программирую код конечного элемента, или, если быть более точным, я изменяю существующую программу, основанную на 2 библиотеках классов, предоставляемых моя способность. Таким образом, я не могу изменять эти классы, потому что они должны быть общими.C++: ошибка: «класс» не имеет члена по имени

Я создал класс 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 либо как доходность объекта ConstVS или BurgersMSrc:

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)?

Любая помощь очень ценится и спасибо заранее за ваши ответы.

Редактировать

FYI, я не очень опытный в C++, но у меня есть некоторый опыт программирования на языке C# и VBA. Однако я хотел бы узнать, так указатели в правильном направлении более чем приветствуется :)

/Edit

соответствующие строки из файла заголовка:

#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 

соответствующие строки СРР-файл:

#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' изменяет личные члены' a_re' и 'a_im' объекта' BurgersMSrc'. Если я выполняю 'p-> calcFourierCoefficient (точность);', я предполагаю, что это изменяет частные члены 'srcTerm', так как' p' определяется как указатель. Это верно? – Eswald

+0

@Eswald No, '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

@ Эсвальд: Существуют различные способы его организации. В вашем примере это казалось хорошим способом структурировать его, поскольку также устраняло необходимость динамического выделения ValSrc, но другие детали вашей проблемы могут сделать другую структуру более чистым. –

Смежные вопросы