C ++ Во время выполнения проверьте, существует ли сигнатура функции?

0

Текущая ситуация такова: я перехожу через код

Изображение 174551

Если вы посмотрите на изображение, текущая ситуация в том, что у меня есть виртуальный метод 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/... Но я действительно не уверен, как реализовать это в своем рабочем процессе, или это даже имеет отношение к моей проблеме.

  • 0
    Тебе нельзя. Вместо этого исправьте свой чрезмерно сложный дизайн (что забавно; вы упомянули об этом сами: «проблема еще больше осложняется тем фактом, что…»).
  • 0
    Из любопытства: по какой причине это должно происходить во время выполнения?
Показать ещё 4 комментария
Теги:
rtti

2 ответа

1

Если изменение класса 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;
}
  • 0
    спасибо, но это не совсем моя ситуация. Если я посмотрю на то, что вы предложили, то теперь у вас есть класс A, который также наследует setData(dataObj) ранее использовался для переопределения setData(int ID) и. Теперь setData(dataObj) можно вызывать через наследование. Но для меня это просто не вариант. Если ранее нам приходилось переопределять setData(int data) для класса A, унаследованного от класса Foo , это означает, что класс A нуждается в специальной обработке, и даже теперь setData(dataObj) также необходимо будет переопределить, поскольку для него потребуется специальная обработка.
  • 0
    Таким образом, этот подход к получению поведения по умолчанию из базы не будет работать.,
1

Вы можете сделать что-то вроде:

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).

  • 0
    Я не эксперт по шаблонам проектирования. Но есть ли какой-то шаблон проектирования, делегирования, функторного подхода, который позволил бы мне сделать это либо более элегантно, либо не касаясь производных классов? С самого начала того, что я видел, это, скорее всего, невозможно. @ Jarod42, я, вероятно, приму этот ответ, если больше ничего не придет. кажется единственным вариантом для наименьшего количества инкрементного изменения кода в части производных классов, чтобы выполнить то, что я пытаюсь.
  • 0
    @thassan: если у вас уже есть посетитель , вы можете использовать его. Иначе вы можете использовать if cascade с dynamic_cast для каждого производного класса, но он менее элегантен, но не затрагивает иерархию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню