вопрос по наследованию с++, специализация типа

PooH

как мне правильно реализовать следующую иерархию?
есть класс AbstractAction
 
 
class AbstractAction
{
public:
AbstractAction;
void do(AbstractItem*);
};

он использует AbstractItem:
 
 
class AbstractItem
{
public:
AbstractItem;
};

мне нужно специализировать класс SpecificAction:
 
 
class SpecificAction : public AbstractAction
{
public:
SpecificAction;
void do(SpecificItem*);
};

при этом метод do по реализации остается таким же, но он должен принимать только SpecificItem*
нужно это для того, чтобы при наследовании от SpecificAction субклассы могли работать с расширенным SpecificItem

PooH

может пример не совсем удачен
более удачная версия:
Есть AbstractAction, есть SpecificAction унаследованный от него
у AbstractAction есть метод void chain(AbstractAction*)
мне нужно, чтобы у SpecificAction был метод void chain(SpecificAction*); при этом реализация этого метода не должна меняться, но оставалась типо-безопасность

apl13

void SpecificAction::chain(AbstractItem *i) { if(dynamic_cast<SpecificItem *>(i AbstractAction::chain(i); }
?
Спасибо, я узнал, что версия чего бы то ни было становится удачнее, если поменять все вхождения do на chain. :ooo:

PooH

спасибо
уже так и сделал
но очень сильно не нравится получившийся интерфейс:
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

PooH

пахнет шаблоном, но очень сильно не хочется
хочется красивого ООП

PooH

реализовал на шаблоне
 
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 

PooH

реализовал в итоге вот так:
 
 
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);
};


работает вроде
Оставить комментарий
Имя или ник:
Комментарий: