2016-08-29 3 views
0

Основой этого является то, что я пытаюсь перегруппировать сложное приложение на 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 
} 

Я тогда следующие классы Наследование от базового класса

model_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 и это определяется как

model_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, я не могу назвать эту функцию, почему?

Большое спасибо за ваше время.

+1

Вы вырезали слишком много необходимой информации, чтобы быть уверенным. Но 'ModeM0 :: getModel()', похоже, ничего не делает для предотвращения разыменования 'i', даже если' i' является конечным итератором. Он также не инициализирует 'm' перед разыменованием. Оба они вызывают неопределенное поведение. Кроме того, 'IMessageSink :: process()' принимает аргумент по ссылке, но 'Model :: process()' принимает аргумент по значению, что означает, что он скрывает, а не переопределяет унаследованную версию. – Peter

+1

Вы используете унифицированный 'm' при вызове' m-> makeA() '. Вероятно, это статический метод, поэтому 'ModelM0 :: makeA()', но тогда он не может быть виртуальным. То же самое для 'makeB'. –

+1

Питер делает некоторые действительные баллы, эти вещи могут не быть индивидуально вашей проблемой, но вместе они могут сделать что-то вроде того, что вы видите – DarthRubik

ответ

1

Вы не можете сделать m->, если m является унифицированным. Это позволит получить доступ к произвольной ячейке памяти (и вызвать дамп).

Если я правильно понял ваш код, вы можете сделать makeA и makeB статическим.

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); 
+0

У меня были статические элементы makeA и 'makeB' перед рефактором, я только что попытался выйти за борт. Это, безусловно, проблема - никогда не похвалить код ... – MoonKnight

3
ModelM0* m; 

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

Вы пытаетесь разыменованием неинициализированным указатель m. Это неопределенное поведение. Трудно сказать, как именно это нужно исправить, не зная детали вашего проекта. Возможно, вместо этого следует использовать какой-то завод.