使用模板动态转换类层次结构
在我的项目中,如果我将基类Base_Dialog定义为非模板,然后尝试在already_exists_中分配“调用者”,它会按预期的方式工作,但如果我将Base_Dialog作为模板类,那么算法“already_exists_”(未更改)将不起作用并且调用者不会改变(这一点特别有趣,算法没有改变,但一旦有效,其他时候则无效):
//This is minimal example (I know it's somewhat longer than usual but in order to show what I mean it needs to be this length)
MAIN_DIALOG_HPP
#ifndef MAIN_DIALOG_HPP
#define MAIN_DIALOG_HPP
#include <QSet>
#include <QtDebug>
#include "Base_Dialog.hpp"
#include "ui_Main_Dialog.h"
#include "_1Dialog.hpp"
#include "_2Dialog.hpp"
/*The following approach will not work*/
class Main_Dialog : public Base_Dialog<Ui::Main_Dialog>
{
/*but if I would do as below (changing Base_Dialog to non-template) it will work:*/
//class Main_Dialog : public QDialog, private Ui::Main_Dialog, public Base_Dialog
Q_OBJECT
QSet<QDialog*>* dialogs_;
private:
template<class Dialog,class Caller>
bool already_created_(Caller*const&, QDialog*& already_exists);
template<class Dialog,class Caller, class Parent>
QDialog* create_(Caller*const&,Parent*const&);
public:
explicit Main_Dialog(QWidget *parent = 0);
template<class Dialog,class Caller>
QDialog* get_dialog(Caller*const& caller);
public slots:
void _1clicked()
{
this->hide();
get_dialog<_1Dialog>(this)->show();
}
void _2clicked()
{
this->hide();
get_dialog<_2Dialog>(this)->show();
}
};
template<class Dialog,class Caller>
bool Main_Dialog::already_created_(Caller*const& caller,QDialog*& already_exists)
{/*the already_exists is introduced here in order to remove repetions of code and
searching*/
auto beg = dialogs_->begin();
auto end = dialogs_->end();
while(beg != end)
{
if(dynamic_cast<Dialog*>(*beg))
{
already_exists = *beg;
static_cast<Base_Dialog*>(already_exists)->set_caller(caller);
return true;
}
++beg;
}
return false;
}
template<class Dialog,class Caller, class Parent>
QDialog* Main_Dialog::create_(Caller *const&caller, Parent *const&parent)
{
return (*dialogs_->insert(new Dialog(this,caller,parent)));
}
template<class Dialog,class Caller>
QDialog* Main_Dialog::get_dialog(Caller *const&caller)
{
QDialog* already_exists = nullptr;
if (already_created_<Dialog>(caller,already_exists))
{
return already_exists;
}
else
{
return create_<Dialog>(caller,this);
}
}
Main_Dialog::Main_Dialog(QWidget *parent) :
Base_Dialog<Ui::Main_Dialog>(this,this,parent),dialogs_(new QSet<QDialog*>)
{
setupUi(this);
}
#endif // MAIN_DIALOG_HPP
BASE_DIALOG_HPP
#ifndef BASE_DIALOG_HPP
#define BASE_DIALOG_HPP
#include <QDialog>
#include <QString>
class Main_Dialog;
template<class Ui_Dialog>
class Base_Dialog : public QDialog, protected Ui_Dialog
{
// Q_OBJECT //no signals/slots
protected:
Main_Dialog* main_dlg_;
QDialog* caller_;
public:
Base_Dialog(Main_Dialog *const &main_dlg, QDialog *const&caller, QWidget *parent = nullptr);
QDialog* set_caller(QDialog *const&);
QDialog* clear_caller();
Main_Dialog* clear_main_dlg();
};
/*----------------*/
//#include "Main_Dialog.hpp"
template<class Ui_Dialog>
Base_Dialog<Ui_Dialog>::Base_Dialog(Main_Dialog *const&main_dlg,QDialog *const&caller, QWidget *parent):
QDialog(parent),
main_dlg_(main_dlg),
caller_(caller)
{
//setupUi(this);
}
#include <QtDebug>
template<class Ui_Dialog>
QDialog* Base_Dialog<Ui_Dialog>::set_caller(QDialog *const&new_caller)
{
QDialog* old_caller = caller_;
caller_ = new_caller;
return old_caller;
}
#endif
_1DIALOG_HPP
#ifndef _1DIALOG_HPP
#define _1DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__1Dialog.h"
class Main_Dialog;
class _1Dialog : public Base_Dialog<Ui::_1Dialog>
{
Q_OBJECT
public:
explicit _1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);
private slots:
void _2clicked();
void caller_clicked();
void main_clicked();
};
#endif // _1DIALOG_HPP
_1Dialog cpp
//_1Dialog cpp
#include "_1Dialog.hpp"
#include "_2Dialog.hpp"
#include "Main_Dialog.hpp"
_1Dialog::_1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
Base_Dialog<Ui::_1Dialog>(main_dlg,caller,parent)
{
setupUi(this);
}
void _1Dialog::_2clicked()
{
this->hide();
main_dlg_->get_dialog<_2Dialog>(this)->show();
}
void _1Dialog::caller_clicked()
{
this->hide();
caller_->show();
}
void _1Dialog::main_clicked()
{
this->hide();
main_dlg_->show();
}
_2DIALOG_HPP
#ifndef _2DIALOG_HPP
#define _2DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__2Dialog.h"
class Main_Dialog;
class _2Dialog : public Base_Dialog<Ui::_2Dialog>//,private Ui::_2Dialog
{
Q_OBJECT
private:
public:
explicit _2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);
private slots:
void _1clicked();
void caller_clicked();
void main_clicked();
};
#endif // _2DIALOG_HPP
_2Dialog cpp
//_2Dialog cpp
#include "_2Dialog.hpp"
#include "_1Dialog.hpp"
#include "Main_Dialog.hpp"
_2Dialog::_2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
Base_Dialog<Ui::_2Dialog>(main_dlg,caller,parent)
{
setupUi(this);
}
void _2Dialog::_1clicked()
{
this->hide();
main_dlg_->get_dialog<_1Dialog>(this)->show();
}
void _2Dialog::caller_clicked()
{
this->hide();
caller_->show();
}
void _2Dialog::main_clicked()
{
this->hide();
main_dlg_->show();
}
为什么会出现这种情况?算法没有改变,但一旦分配正确,而另一次分配不正确?
in my project if I define base class Base_Dialog as non template and then try to assign 'caller' in already_exists_ it works in the way expected but if I make Base_Dialog as a template class then the algorithm 'already_exists_' (unchanged) will not work and caller will not change (this is especially intriguing that the algorithm is unchanged and yet once works and other time it doesn't):
//This is minimal example (I know it's somewhat longer than usual but in order to show what I mean it needs to be this length)
MAIN_DIALOG_HPP
#ifndef MAIN_DIALOG_HPP
#define MAIN_DIALOG_HPP
#include <QSet>
#include <QtDebug>
#include "Base_Dialog.hpp"
#include "ui_Main_Dialog.h"
#include "_1Dialog.hpp"
#include "_2Dialog.hpp"
/*The following approach will not work*/
class Main_Dialog : public Base_Dialog<Ui::Main_Dialog>
{
/*but if I would do as below (changing Base_Dialog to non-template) it will work:*/
//class Main_Dialog : public QDialog, private Ui::Main_Dialog, public Base_Dialog
Q_OBJECT
QSet<QDialog*>* dialogs_;
private:
template<class Dialog,class Caller>
bool already_created_(Caller*const&, QDialog*& already_exists);
template<class Dialog,class Caller, class Parent>
QDialog* create_(Caller*const&,Parent*const&);
public:
explicit Main_Dialog(QWidget *parent = 0);
template<class Dialog,class Caller>
QDialog* get_dialog(Caller*const& caller);
public slots:
void _1clicked()
{
this->hide();
get_dialog<_1Dialog>(this)->show();
}
void _2clicked()
{
this->hide();
get_dialog<_2Dialog>(this)->show();
}
};
template<class Dialog,class Caller>
bool Main_Dialog::already_created_(Caller*const& caller,QDialog*& already_exists)
{/*the already_exists is introduced here in order to remove repetions of code and
searching*/
auto beg = dialogs_->begin();
auto end = dialogs_->end();
while(beg != end)
{
if(dynamic_cast<Dialog*>(*beg))
{
already_exists = *beg;
static_cast<Base_Dialog*>(already_exists)->set_caller(caller);
return true;
}
++beg;
}
return false;
}
template<class Dialog,class Caller, class Parent>
QDialog* Main_Dialog::create_(Caller *const&caller, Parent *const&parent)
{
return (*dialogs_->insert(new Dialog(this,caller,parent)));
}
template<class Dialog,class Caller>
QDialog* Main_Dialog::get_dialog(Caller *const&caller)
{
QDialog* already_exists = nullptr;
if (already_created_<Dialog>(caller,already_exists))
{
return already_exists;
}
else
{
return create_<Dialog>(caller,this);
}
}
Main_Dialog::Main_Dialog(QWidget *parent) :
Base_Dialog<Ui::Main_Dialog>(this,this,parent),dialogs_(new QSet<QDialog*>)
{
setupUi(this);
}
#endif // MAIN_DIALOG_HPP
BASE_DIALOG_HPP
#ifndef BASE_DIALOG_HPP
#define BASE_DIALOG_HPP
#include <QDialog>
#include <QString>
class Main_Dialog;
template<class Ui_Dialog>
class Base_Dialog : public QDialog, protected Ui_Dialog
{
// Q_OBJECT //no signals/slots
protected:
Main_Dialog* main_dlg_;
QDialog* caller_;
public:
Base_Dialog(Main_Dialog *const &main_dlg, QDialog *const&caller, QWidget *parent = nullptr);
QDialog* set_caller(QDialog *const&);
QDialog* clear_caller();
Main_Dialog* clear_main_dlg();
};
/*----------------*/
//#include "Main_Dialog.hpp"
template<class Ui_Dialog>
Base_Dialog<Ui_Dialog>::Base_Dialog(Main_Dialog *const&main_dlg,QDialog *const&caller, QWidget *parent):
QDialog(parent),
main_dlg_(main_dlg),
caller_(caller)
{
//setupUi(this);
}
#include <QtDebug>
template<class Ui_Dialog>
QDialog* Base_Dialog<Ui_Dialog>::set_caller(QDialog *const&new_caller)
{
QDialog* old_caller = caller_;
caller_ = new_caller;
return old_caller;
}
#endif
_1DIALOG_HPP
#ifndef _1DIALOG_HPP
#define _1DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__1Dialog.h"
class Main_Dialog;
class _1Dialog : public Base_Dialog<Ui::_1Dialog>
{
Q_OBJECT
public:
explicit _1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);
private slots:
void _2clicked();
void caller_clicked();
void main_clicked();
};
#endif // _1DIALOG_HPP
_1Dialog cpp
//_1Dialog cpp
#include "_1Dialog.hpp"
#include "_2Dialog.hpp"
#include "Main_Dialog.hpp"
_1Dialog::_1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
Base_Dialog<Ui::_1Dialog>(main_dlg,caller,parent)
{
setupUi(this);
}
void _1Dialog::_2clicked()
{
this->hide();
main_dlg_->get_dialog<_2Dialog>(this)->show();
}
void _1Dialog::caller_clicked()
{
this->hide();
caller_->show();
}
void _1Dialog::main_clicked()
{
this->hide();
main_dlg_->show();
}
_2DIALOG_HPP
#ifndef _2DIALOG_HPP
#define _2DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__2Dialog.h"
class Main_Dialog;
class _2Dialog : public Base_Dialog<Ui::_2Dialog>//,private Ui::_2Dialog
{
Q_OBJECT
private:
public:
explicit _2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);
private slots:
void _1clicked();
void caller_clicked();
void main_clicked();
};
#endif // _2DIALOG_HPP
_2Dialog cpp
//_2Dialog cpp
#include "_2Dialog.hpp"
#include "_1Dialog.hpp"
#include "Main_Dialog.hpp"
_2Dialog::_2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
Base_Dialog<Ui::_2Dialog>(main_dlg,caller,parent)
{
setupUi(this);
}
void _2Dialog::_1clicked()
{
this->hide();
main_dlg_->get_dialog<_1Dialog>(this)->show();
}
void _2Dialog::caller_clicked()
{
this->hide();
caller_->show();
}
void _2Dialog::main_clicked()
{
this->hide();
main_dlg_->show();
}
Why is this behavior? Algorithm is unchanged and yet once it assigns correctly and the other time it doesn't?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 has_exists_ 中将 line: 更改
为:
并在 Base_Dialog @sehe 中为 QDialog 添加虚拟继承
,我要感谢您为我指明了正确的方向,这使我能够解决这个问题。非常感谢,+1;
In already_exists_ change line:
to:
and add virtual inheritance for QDialog in Base_Dialog
@sehe, I want to thank you for pointing me into right direction, which allow me to resolve this problem. Great thanks, +1;