抽象类层次结构和访问冲突

Abstract Class Hierarchy and Access Violation

本文关键字:访问冲突 层次结构 抽象类      更新时间:2023-10-16

这件事的背景是我试图重新考虑一个复杂的C++应用程序。我把下面的代码放在一起,作为我正在处理的代码的精简版本(去掉不重要的方法等(。我可能在做一些愚蠢的事情,因为我已经多年没有接触C++了,但我可以看到。。。

我有以下几类

message_sink.h:

class IMessageSink
{
public:
    virtual ~IMessageSink() { };
    virtual void process(const Message& msg) = 0;
};

具有以下基本类

model_base.h:

class Model : public virtual IMessageSink
{
public:
   Model(Tag a);
   virtual Model* makeA(Tag a) = 0;
   void reset();
private:
   friend class EM;
   const Tag _a;
   virtual void calculate(double lambda) = 0;
};

其中model_base.cpp

Model::Model(Tag a) : _a(a) { }
void Model::reset()
{
   // ... some implementation
}
void Model::process(const Message msg)
{
    // ... some implementation
}

然后我有以下从基类继承的类

型号_m0.h:

class ModelM0 : public virtual Model
{
public:
    ModelM0(Tag a);        
    ModelM0* make(Tag a);
private:
    void calculate(double lambda);
};

model_m0.cpp:

ModelM0::ModelM0(Tag a) : Model(a) { }
ModelM0* ModelM0::make(Tag a)
{
   ModelM0* m = new ModelM0(a);
   m->reset();
   return m;
}
void ModelM0::calculate(double lambda)
{
    // Some code...
}

但问题就在这里,我有另一个类ModelM0Holder,它被定义为

型号_m0_holder.h:

class ModelM0Holder : public IMessageSink
{
public:
    static ModelM0Holder* make(Tag a)
    {
        return new ModelM0Holder(a);
    }
    ModelM0Holder(Tag a);
    ~ModelM0Holder();
    void process(const Message& msg);
private:
    ModelM0* getModel(int line);
};

model_m0_holder.cpp:

ModelM0Holder::ModelM0Holder(Tag a) : _a(a) { } 
ModelM0Holder::~ModelM0Holder()
{
    // ... some implementation
}
void ModelM0Holder::process(const Message& msg)
{
    // ... some implementation
}
ModelM0* ModelM0Holder::getModel(int ag)
{
    ModelM0* m;
    m = m->make(_a); // Access Violation Exception.
    // ... 
}

当我调用ModelM0Holder::getModel时,我得到了一个AccessViolationException,我不能调用这个函数,为什么?

非常感谢您抽出时间。

ModelM0* m;
if (_period == tau::PERIOD_A)
    m = m->makeA(_newObsTag); // Access Violation Exception.
else
    m = m->makeB(_newObsTag);

您正试图取消引用未初始化的指针m。这是一种未定义的行为。在不了解项目细节的情况下,很难判断到底应该如何修复。也许应该使用某种工厂。

m单元化时,不能执行m->。这将访问一个随机内存位置(并导致转储(。

如果我正确理解了您代码的意图,您可以使makeAmakeB成为静态的。

class ModelM0 : public virtual Model
{
public:
    . . .    
    static ModelM0* makeA(Tag newObsTag);
    static ModelM0* makeB(Tag newObsTag);
    . . .    
};

然后将getModel更改为如下所示:

    ModelM0* m;
    if (_period == tau::PERIOD_A)
        m = ModelM0::makeA(_newObsTag);
    else
        m = ModelM0::makeB(_newObsTag);