Текущая ситуация такова: я перехожу через код
Если вы посмотрите на изображение, текущая ситуация в том, что у меня есть виртуальный метод setData(int ID);
теперь мы хотим изменить это на виртуальный метод setData(dataObj aObj);
Но, делая это, это долгий процесс, так как наш объект foo
был унаследован множеством классов. Итак, мы хотим постепенно изменить код.
Таким образом, мне нужно сделать, чтобы проверить, setData(dataObj aObj)
ли один из унаследованных классов setData(dataObj aObj)
этот класс, иначе вызовите другую предыдущую сигнатуру функции setData(int ID);
Проблема осложняется еще и тем, что класс FOO
предоставляет ранее setData(int ID)
по умолчанию, а не все классы, наследующие FOO
таким образом, возможно, может и не понадобиться реализовать setData
и их реализация сильно варьируется.
Я уже посмотрел, как проверить, существует ли функция в C/C++, которая не отвечает на мои вопросы.
В некоторых из сообщений, которые я видел, люди используют шаблоны, это не вариант для меня, так как это нужно делать во время выполнения. Другие варианты, похоже, предполагают уловки/манипуляции с GCC и т.д. Мне нужно, чтобы мой код был независимым от платформы и компилятора. Так что это тоже не вариант.
Любые другие предложения, единственное возможное закрытое решение, похоже, qaru.site/questions/287069/... Но я действительно не уверен, как реализовать это в своем рабочем процессе, или это даже имеет отношение к моей проблеме.
Если изменение класса dataObj является опцией, а создание и уничтожение объектов dataObj не слишком дороги, вы можете рассмотреть следующее. Мне это не особенно нравится, но, поскольку краткосрочные взломы идут, я видел хуже...
class dataObj
{
int x;
public:
int getID(void) const {
std::cout << "dataObj::getID " << std::endl;
return x;
}
dataObj() : x(0){}
~dataObj(){}
};
class Foo
{
public:
// Old interface
virtual void setData(int ID) {
/* Old default implementation */
std::cout << "Foo::setData int" << std::endl;
}
// New interface
virtual void setData(const dataObj& aObj) {
/* New default implementation */
std::cout << "Foo::setData dataObj" << std::endl;
setData(aObj.getID());
}
};
class A : public Foo
{
public:
virtual void setData(int ID) {
/* Old default implementation */
std::cout << "A:: setData int" << std::endl;
}
};
class B : public Foo
{
public:
virtual void setData(const dataObj& aObj) {
/* Old default implementation */
std::cout << "B:: setData dataObj" << std::endl;
}
};
int main(int argc, char* argv[])
{
A a;
B b;
dataObj d;
Foo* pa, * pb;
pa = &a;
pb = &b;
pa->setData(d);
pb->setData(d);
return 0;
}
setData(dataObj)
ранее использовался для переопределения setData(int ID)
и. Теперь setData(dataObj)
можно вызывать через наследование. Но для меня это просто не вариант. Если ранее нам приходилось переопределять setData(int data)
для класса A, унаследованного от класса Foo
, это означает, что класс A нуждается в специальной обработке, и даже теперь setData(dataObj)
также необходимо будет переопределить, поскольку для него потребуется специальная обработка.
Вы можете сделать что-то вроде:
class Foo
{
public:
// Old interface
virtual void setData(int ID) { /* Old default implementation */ }
// New interface
virtual void setData(dataObj aObj) { /* New default implementation */ }
void init() {
if (useOldInterface()) {
setData(ID);
} else {
setData(aObj);
}
}
private:
// temporary method to be removed once all derived classes return false.
virtual bool useOldInterface() const { return true; }
};
И измените постепенно производные классы, добавив
virtual bool useOldInterface() const override { return false; }
и соответствующие void setData(dataObj aObj)
.
if
cascade с dynamic_cast
для каждого производного класса, но он менее элегантен, но не затрагивает иерархию.