вопрос по наследованию с++, специализация типа
более удачная версия:
Есть AbstractAction, есть SpecificAction унаследованный от него
у AbstractAction есть метод void chain(AbstractAction*)
мне нужно, чтобы у SpecificAction был метод void chain(SpecificAction*); при этом реализация этого метода не должна меняться, но оставалась типо-безопасность
void SpecificAction::chain(AbstractItem *i) { if(dynamic_cast<SpecificItem *>(i AbstractAction::chain(i); }?
Спасибо, я узнал, что версия чего бы то ни было становится удачнее, если поменять все вхождения do на chain.
уже так и сделал
но очень сильно не нравится получившийся интерфейс:
void SpecificAction::chain(AbstractItem *i)
хочу
void SpecificAction::chain(SpecificItem *i)
проблема теперь в следующем:
class AbstractAction
{
Q_OBJECT
AbstractAction* chainedAction;
public:
explicit AbstractAction(QObject* parent = 0);
public slots:
virtual void exec(AbstractItem* item);
virtual void undo(AbstractItem* file);
void chain(AbstractAction* action);
void unchain;
signals:
void done(AbstractItem* item);
void nextExec(AbstractItem* item);
void error(AbstractItem* item, QString msg);
void undone(AbstractItem* item);
void nextUndo(AbstractItem* item);
};
class AbstractFileAction : public AbstractAction
{
Q_OBJECT
public:
explicit AbstractFileAction(QObject* parent = 0);
public slots:
virtual void exec(File* file);
virtual void undo(File* file);
void chain(AbstractFileAction* action);
void unchain;
signals:
void done(File* file);
void nextExec(File* file);
void error(File* file, QString msg);
void undone(File* file);
void nextUndo(File* file);
};
void AbstractAction::chain(AbstractAction *action) {
if(chainedAction != NULL) {
unchain;
}
log(QString("chaining action %1").arg(action->metaObject->className;
disconnect(this, SIGNAL(nextExec(AbstractItem* this, SIGNAL(done(AbstractItem*;
disconnect(this, SIGNAL(nextUndo(AbstractItem* this, SIGNAL(undone(AbstractItem*;
chainedAction = action;
connect(this, SIGNAL(nextExec(AbstractItem* chainedAction, SLOT(exec(AbstractItem*;
connect(this, SIGNAL(nextUndo(AbstractItem* chainedAction, SLOT(undo(AbstractItem*;
connect(chainedAction, SIGNAL(done(AbstractItem* SIGNAL(done(AbstractItem*;
connect(chainedAction, SIGNAL(undone(AbstractItem* SIGNAL(undone(AbstractItem*;
connect(chainedAction, SIGNAL(error(AbstractItem*,QString SIGNAL(error(AbstractItem*,QString;
log(QString("action %1 chained").arg(action->metaObject->className;
}
void AbstractAction::unchain {
log(QString("unchaining action %1").arg(chainedAction->metaObject->className;
disconnect(chainedAction);
connect(this, SIGNAL(nextExec(AbstractItem* SIGNAL(done(AbstractItem*;
connect(this, SIGNAL(nextUndo(AbstractItem* SIGNAL(undone(AbstractItem*;
chainedAction = NULL;
log(QString("action %1 unchained").arg(chainedAction->metaObject->className;
}
хочу странного:
чтобы работало AbstractFileAction::chain с AbstractFileAction
в чем проблема:
AbstractAction::chain(AbstractAction*)
присоединяет nextExec(AbstractItem*) c exec(AbstractItem*)
я же хочу чтобы
AbstractFileAction::chain(AbstractFileAction*)
присоединялnextExec(File*) к exec(File*)
при этом менялся бы только тип AbstractItem* -> File*
пока что приходится дублировать код chain
хочется красивого ООП
template <typename ItemType>
class AbstractAction : public Logger
{
Q_OBJECT
AbstractAction* chainedAction;
public:
explicit AbstractAction(QObject* parent = 0) :
Logger(parent
chainedAction(NULL)
{
connect(this, SIGNAL(nextExec(ItemType* SIGNAL(done(ItemType*;
connect(this, SIGNAL(nextUndo(ItemType* SIGNAL(undone(ItemType*;
}
public slots:
virtual void exec(ItemType*) {}
virtual void undo(ItemType*) {}
void chain(AbstractAction<ItemType>* action) {
if(chainedAction != NULL) {
unchain;
}
log(QString("chaining action %1").arg(action->metaObject->className;
disconnect(this, SIGNAL(nextExec(ItemType* this, SIGNAL(done(ItemType*;
disconnect(this, SIGNAL(nextUndo(ItemType* this, SIGNAL(undone(ItemType*;
chainedAction = action;
connect(this, SIGNAL(nextExec(ItemType* chainedAction, SLOT(exec(ItemType*;
connect(this, SIGNAL(nextUndo(ItemType* chainedAction, SLOT(undo(ItemType*;
connect(chainedAction, SIGNAL(done(ItemType* SIGNAL(done(ItemType*;
connect(chainedAction, SIGNAL(undone(ItemType* SIGNAL(undone(ItemType*;
connect(chainedAction, SIGNAL(error(ItemType*,QString SIGNAL(error(ItemType*,QString;
log(QString("action %1 chained").arg(action->metaObject->className;
}
void unchain {
log(QString("unchaining action %1").arg(chainedAction->metaObject->className;
disconnect(chainedAction);
connect(this, SIGNAL(nextExec(ItemType* SIGNAL(done(ItemType*;
connect(this, SIGNAL(nextUndo(ItemType* SIGNAL(undone(ItemType*;
chainedAction = NULL;
log(QString("action %1 unchained").arg(chainedAction->metaObject->className;
}
signals:
void done(ItemType* item);
void nextExec(ItemType* item);
void error(ItemType* item, QString msg);
void undone(ItemType* item);
void nextUndo(ItemType* item);
void progress(quint64 current, quint64 total);
void description(QString);
};
и облом
ошибка: Template classes not supported by Q_OBJECT
class AbstractAction : public Logger
{
Q_OBJECT
AbstractAction* chainedAction;
public:
explicit AbstractAction(QObject* parent = 0);
public slots:
virtual void exec(AbstractItem*) {}
virtual void undo(AbstractItem*) {}
void chain(AbstractAction* action);
void unchain;
signals:
void done(AbstractItem* item);
void nextExec(AbstractItem* item);
void error(AbstractItem* item, QString msg);
void undone(AbstractItem* item);
void nextUndo(AbstractItem* item);
};
class AbstractFileAction : public AbstractAction
{
Q_OBJECT
public:
explicit AbstractFileAction(QObject* parent = 0);
public slots:
void exec(AbstractItem* item) {
if(dynamic_cast<File*>(item {
log("item type compatible, processing");
exec(dynamic_cast<File*>(item;
} else {
log("item type incompatible, ignoring");
emit nextExec(item);
}
}
void undo(AbstractItem* item) {
if(dynamic_cast<File*>(item {
log("item type compatible, processing");
undo(dynamic_cast<File*>(item;
} else {
log("item type incompatible, ignoring");
emit nextUndo(item);
}
}
virtual void exec(File*) {}
virtual void undo(File*) {}
signals:
void progress(qint64 current, qint64 total);
void description(QString);
};
работает вроде
Оставить комментарий
PooH
как мне правильно реализовать следующую иерархию?есть класс AbstractAction
он использует AbstractItem:
мне нужно специализировать класс SpecificAction:
при этом метод do по реализации остается таким же, но он должен принимать только SpecificItem*
нужно это для того, чтобы при наследовании от SpecificAction субклассы могли работать с расширенным SpecificItem