我遇到了一个运行时错误,在调试时将变量列为无法访问。关于这个主题还有其他帖子,但修复不适合我。
我使用QtCreator 4.5.1和Qt lib 5.10(Mingw32 5.3,MSVC14 x64,MSVC x64)
我已经按照disable pretty printers post的建议禁用了“加载系统GDB漂亮的打印机”。
失败代码的含义:
为了在我的解耦QtQuick2视图模型之间进行通信,我实现了一个简单版本的EventAgregator模式。
实施仍然缺少线程安全和清理不再存在的订户。但是它与我的错误无关。
相关代码文件:
qspinstartup.h
class QSpinStartup:QObject
{
public:
QSpinStartup();
bool loadQSpin(const QString dir, const QString startView="");
private:
void registerQmlGui();
void registerQmlViewModel();
QQmlApplicationEngine engine;
//constant viewmodel objects
CodeEditorTab* codeEditor;
VerificationTab* verificationEditor;
QSpinMessageService msgService;
};
qspinstartup.cpp
QSpinStartup::QSpinStartup():QObject()
,verificationEditor(new VerificationTab(msgService,this))
,codeEditor(new CodeEditorTab(msgService,this))
//,console(new ConsoleEditor(msgService,this))
{
registerQmlGui();
registerQmlViewModel();
initPointerObjects();
auto ctx = engine.rootContext();
qSpinNullPtrCheck(ctx);
PrintToConsole p("pri");
msgService.publish<PrintToConsole>(p);
ctx->setContextProperty("codeEditorVm",codeEditor);
}
bool QSpinStartup::loadQSpin(const QString dir,const QString startView)
{
QDir ldir(dir);
QString l = ldir.entryList(QStringList()<<startView,QDir::Files).first();
qInfo()<<l;
engine.load(QUrl(l.prepend("qrc:/")));
bool isReady = engine.rootObjects().count()>0;
qSpinSafeFail(!isReady,"Qml Application failed to start engine");
return isReady;
}
void QSpinStartup::registerQmlGui()
{
QSpinWorkSpace::Workspace::registerAsQml();
}
void QSpinStartup::registerQmlViewModel()
{
VerificationTab::registerAsQml();
CodeEditorTab::registerAsQml();
ConsoleEditor::registerAsQml();
}
ieventbase.h
class IEventBase{
public:
enum Types{ // <--simple way to give an object a type specifier
PrintToConsole,
CurrentDocumentChanged,
CompilerOptions,
SpinArgCommand
};
IEventBase(Types t):type(t){}
const Types type;
};
qspinmessageservice.h
template<class T>
class ISubscriber{
public:
virtual ~ISubscriber(){}
virtual void executeSubscribed(T& event)=0;
};
class QSpinMessageService: public QObject{
Q_OBJECT
typedef QPointer<QObject> subscriber;
typedef QVector<subscriber> EvAgrList;
QHash<IEventBase::Types,EvAgrList> subs;
public:
QSpinMessageService(QObject* parent=nullptr):QObject(parent)
,subs(QHash<IEventBase::Types,EvAgrList>()){}
void subscribe(QObject *obj, IEventBase::Types key){
if(!subs.contains(key)) // <-- this line cause my error
subs[key]= EvAgrList();
EvAgrList& list = subs[key];
list<<subscriber(obj);
}
template<typename T>
void publish(typename T::IEventBase execute){
EvAgrList lSubs = subs[execute.type];
for(int i=0; i<lSubs.count();i++){
subscriber&q = lSubs[i];
if(q.isNull()){
lSubs.removeOne(q);
--i;
continue;
}
ISubscriber<T>* a = dynamic_cast<ISubscriber<T>*>(q.data());
qDebug()<< q<<a;
//ISubscriber<T>* s = dynamic_cast<ISubscriber<T>*>(q);
a->executeSubscribed(static_cast<T&>(execute));
}
}
};
static QSpinMessageService dummy;
verificationtab.cpp(它是一个很大的类,所以我排除了不相关的部分)
VerificationTab::VerificationTab(QSpinMessageService &service, QObject *parent) :
QSpinTab(parent,"Verification",QSpinTabType::Verification)
,msgService(service)
,m_stateProp(new StateSpaceProp(this)),m_stateSpec(new StateSpaceSpec(this))
,m_memoryUsage(new MemoryUsage(this)),m_settings(new VerificationSettings(this))
{
msgService.subscribe(this,IEventBase::CurrentDocumentChanged); // <-- error call
//if the line above is commented out the application runs
}
Github repository of the full application
注意:
在将文件添加到主项目之前,我在单独的空项目中设计了QSpin MessageService。订阅方法适用于该项目。
知道怎么解决这个问题吗?
我终于找到了我的错误原因。尽管Debug Watch列表指出QSpinMessageService对象存在,但此时还没有进行过prberly初始化。为什么subscribe()甚至能够被访问超出了我目前的cpp技能。
修复:在qspinstartup.cpp中,构造函数需要更改如下。
qspinstartup.cpp
QSpinStartup::QSpinStartup():QObject()
{
codeEditor = new CodeEditorTab(msgService,this);
verificationEditor = new VerificationTab(&msgService,this);
registerQmlGui();
registerQmlViewModel();
auto ctx = engine.rootContext();
qSpinNullPtrCheck(ctx);
PrintToConsole p("pri");
msgService.publish<PrintToConsole>(p);
ctx->setContextProperty("codeEditorVm",codeEditor);
}