【问题标题】:C++: error: ‘class’ has no member namedC++:错误:“类”没有名为的成员
【发布时间】:2013-06-01 13:39:39
【问题描述】:

对于我的毕业论文,我正在编写一些有限元代码,或者更准确地说,我正在修改一个现有程序,该程序基于我的教师提供的 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;

}

【问题讨论】:

  • 我在该领域不是很了解,但考虑使用动态演员表。如果您尝试将基类动态转换为派生类,它应该抛出异常

标签: c++ class inheritance polymorphism member


【解决方案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
}

【讨论】:

  • 谢谢,我会调查的!
  • 好吧,我已经解释过了,在修复了我的类文件设置中的一些其他错误之后,我让它在我的验证程序上运行。还有一个问题,完全是因为我缺乏C++经验和知识:calculateFourierCoefficient修改了BurgersMSrc-object的私有成员a_rea_im。如果我执行p-&gt;calcFourierCoefficient(accuracy);,我假设这会改变srcTerm 的私有成员,因为p 被定义为一个指针。这是正确的吗?
  • @Eswald 不,BurgersMSrc::calculateFourierTransform 不能看到基类的私有成员,即使可以看到,BurgersMSrc 的类似名称成员仍然优先,无论函数如何叫。一个函数不知道它是在指针、引用还是对象上分派的,如果知道,它不会有任何区别。
  • @Eswald 你有一个指向ValSrc 的指针,名为srcTerm。您实例化(创建一个实例)类BurgersMSrc,并指定srcTerm 指向该实例。您创建了一个指向 BurgersMSrc 的指针,名为 p。您将指针srcTerm 动态转换为指向BurgersMSrc 的指针,并根据此转换的结果初始化p两个指针都指向你用new BurgersMSrc创建的对象;他们只是对其类型的了解有所不同。
  • @Eswald 指针不“记住”它是如何初始化的。它不知道它指向的对象是来自new 还是dynamic_cast 或其他任何东西。它只是假设它在其声明中指向该类的一个实例(在本例中为BurgersMSrc* p)。
【解决方案2】:

这对您的问题来说可能有点过头了,但我想提出一个替代解决方案。

在面向对象的程序中,必须使用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;
}

【讨论】:

  • 所以如果正确解释这个,主程序的所有代码都包含在结构Problem中?如果是这样,它确实看起来有点矫枉过正,因为它涉及大量重写,因为涉及到许多其他类和对象。虽然我肯定在这个解决方案中看到了一些优势。我可能会和我的教授讨论:)。
  • @Eswald:有多种组织方式。在您的示例中,这似乎是一种构造它的好方法,因为它还消除了动态分配 ValSrc 的需要,但是您的问题的其他细节可能会使其他一些结构更清晰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2013-12-06
  • 1970-01-01
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多