C++ 带模板的动态强制类型转换类层次结构
在我的项目中,如果我将基类base_Dialog定义为非模板,然后尝试在“已存在”中分配“调用者”,它会以预期的方式工作,但如果我将base_Dialog作为模板类,则算法“已存在”(未更改)将不起作用,调用者也不会更改(尤其有趣的是,该算法没有改变,但一旦成功,其他时间就没有了): 主对话框水电站C++ 带模板的动态强制类型转换类层次结构,c++,templates,multiple-inheritance,dynamic-cast,C++,Templates,Multiple Inheritance,Dynamic Cast,在我的项目中,如果我将基类base_Dialog定义为非模板,然后尝试在“已存在”中分配“调用者”,它会以预期的方式工作,但如果我将base_Dialog作为模板类,则算法“已存在”(未更改)将不起作用,调用者也不会更改(尤其有趣的是,该算法没有改变,但一旦成功,其他时间就没有了): 主对话框水电站 \ifndef主对话框\u水电站 #定义主对话框\u水电站 #包括 #包括 #包括“Base_Dialog.hpp” #包括“ui\u Main\u Dialog.h” #包括“\u 1Dialog
\ifndef主对话框\u水电站
#定义主对话框\u水电站
#包括
#包括
#包括“Base_Dialog.hpp”
#包括“ui\u Main\u Dialog.h”
#包括“\u 1Dialog.hpp”
#包括“\u 2Dialog.hpp”
/*以下方法行不通*/
类主对话框:公共基对话框
{
/*但是,如果我按照以下方法(将Base_对话框更改为non-template)操作,它将起作用:*/
//类主对话框:公共QDialog,私有Ui::主对话框,公共基对话框
Q_对象
QSet*对话框;
私人:
样板
bool已创建(调用者*const&,QDialog*&已存在);
样板
QDialog*创建(调用者*const&,父*const&);
公众:
显式主对话框(QWidget*parent=0);
样板
QDialog*get_对话框(调用者*const&调用者);
公众时段:
void_1clicked()
{
这个->隐藏();
获取对话框(此)->show();
}
void 2clicked()
{
这个->隐藏();
获取对话框(此)->show();
}
};
样板
bool主对话框::已创建(调用者*常量和调用者,QDialog*&已存在)
{/*此处引入已存在的_,以消除代码和
搜寻*/
自动beg=对话框->开始();
自动结束=对话框->结束();
while(beg!=结束)
{
if(动态施法(*beg))
{
已经存在=*beg;
静态\u cast(已存在)->设置\u调用者(调用者);
返回true;
}
++乞讨;
}
返回false;
}
样板
QDialog*主对话框::创建(调用者*常量和调用者,父对象*常量和父对象)
{
返回(*对话框->插入(新对话框(此、调用方、父级));
}
样板
QDialog*主对话框::获取对话框(调用者*常量和调用者)
{
QDialog*已存在=空ptr;
if(已创建)(调用者,已存在))
{
返回已经存在;
}
其他的
{
返回create(调用者,this);
}
}
主对话框::主对话框(QWidget*父项):
基本对话框(此,此,父级),对话框(新QSet)
{
setupUi(本);
}
#endif//MAIN\u DIALOG\u水电站
基础水电站
\ifndef BASE\u DIALOG\u水电站
#定义基础\u对话框\u水电站
#包括
#包括
类主对话框;
样板
类基本对话框:公共QDialog,受保护的Ui对话框
{
//Q_对象//无信号/插槽
受保护的:
主对话框*主对话框;
QDialog*调用者u;
公众:
基本对话框(主对话框*常量和主对话框,QDialog*常量和调用者,QWidget*父项=nullptr);
QDialog*set_调用者(QDialog*const&);
QDialog*清除调用者();
主对话框*清除主对话框();
};
/*----------------*/
//#包括“Main_Dialog.hpp”
样板
基本对话框::基本对话框(主对话框*常量和主对话框,QDialog*常量和调用者,QWidget*父项):
QDialog(父级),
主要的(主要的),,
呼叫者(呼叫者)
{
//setupUi(本);
}
#包括
样板
QDialog*Base\u对话框::设置调用方(QDialog*const和new\u调用方)
{
QDialog*old\u caller=调用者;
调用者\新的\调用者;
返回老呼叫者;
}
#恩迪夫
_1 Dialog_水电站
\ifndef\u 1DIALOG\u水电站
#定义\u 1对话框\u水电站
#包括“Base_Dialog.hpp”
#包括“ui\uu 1Dialog.h”
类主对话框;
类对话框:公共基对话框
{
Q_对象
公众:
显式对话框(主对话框*Main\u dlg,QDialog*调用者,QWidget*parent=0);
专用插槽:
void _2clicked();
void caller_clicked();
void main_clicked();
};
#endif/\u 1DIALOG\u水电站
_1对话cpp
/\u 1Dialog cpp
#包括“\u 1Dialog.hpp”
#包括“\u 2Dialog.hpp”
#包括“Main_Dialog.hpp”
_1对话框::\u 1对话框(主对话框*Main\u dlg,QDialog*调用者,QWidget*父对象):
基本对话框(主对话框、调用者对话框、父对话框)
{
setupUi(本);
}
void\u 1对话框::\u 2单击()
{
这个->隐藏();
主对话框->获取对话框(此)->显示();
}
void _1Dialog::调用者_单击()
{
这个->隐藏();
调用者->显示();
}
void _1Dialog::main_clicked()
{
这个->隐藏();
主菜单->显示();
}
_2 Dialog_水电站
\ifndef\u 2DIALOG\u水电站
#定义\u 2对话框\u水电站
#包括“Base_Dialog.hpp”
#包括“ui\uu 2Dialog.h”
类主对话框;
类_2Dialog:public Base _Dialog/,private Ui::_2Dialog
{
Q_对象
私人:
公众:
显式对话(主对话*Main\u dlg,QDialog*调用者,QWidget*父项=0);
专用插槽:
void _1clicked();
void caller_clicked();
void main_clicked();
};
#endif/\u 2DIALOG\u水电站
_2对话式cpp
/\u 2对话cpp
#包括“\u 2Dialog.hpp”
#包括“\u 1Dialog.hpp”
#包括“Main_Dialog.hpp”
_2对话框::\u 2对话框(主对话框*Main\u dlg,QDialog*调用者,QWidget*父对象):
基本对话框(主对话框、调用者对话框、父对话框)
{
setupUi(本);
}
void\u 2对话框::\u 1单击()
{
这个->隐藏();
主对话框->获取对话框(此)->显示();
}
void _2Dialog::调用者_单击()
{
这个->隐藏();
调用者->显示();
}
void _2Dialog::main_clicked()
{
这个->隐藏();
主菜单->显示();
}
为什么会出现这种行为?算法是不变的,但一旦分配正确,而另一次分配不正确?在“已存在”中更改行:
static_cast<Base_Dialog*>(already_exists)->set_caller(caller);
static\u cast(已经存在)->set\u调用者(调用者);
致:
static\u cast(已经存在)->set\u调用者(调用者);
并在Base_对话框中为QDialog添加虚拟继承
@sehe,我想感谢您为我指明了正确的方向,这使我能够解决这个问题。非常感谢,+1;请阅读。然后停止使用开头的标识符
#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
#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
#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
#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();
}
#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
#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();
}
static_cast<Base_Dialog*>(already_exists)->set_caller(caller);
static_cast<Dialog*>(already_exists)->set_caller(caller);