Добавить функции расширения в существующий класс без изменения исходного кода класса

0

У меня есть большое приложение C++, которое использует старую версию библиотеки с открытым исходным кодом. Я хочу перейти на новую библиотеку. В новой библиотеке старая функция fnOldFunction() удаляется и добавляется новая функция fnNewFunction(). Теперь у меня есть два варианта:

  1. Замените все экземпляры fnOldFunction() на fnNewFunction(). У меня есть много других функций, таких как fnOldFunction(), я не хочу иметь дело с n функциями с тысячами находок и заметок.

  2. У меня есть исходный код библиотеки. Я могу добавить fnOldFunction() и вызвать fnNewFunction из fnOldFunction(). Но даже у меня есть исходный код этого libray, не хочу вносить какие-либо изменения в исходный код libray.

Может ли кто-нибудь дать мне другой способ добиться того же. Я знаю, что некоторые языки, такие как Ruby, Javascript, Objective C, предоставляют возможность расширения/изменения существующего класса без изменения исходного кода этого класса. Но C++ не хватает этой возможности.

  • 0
    C ++ не имеет методов расширения. Вы буквально не можете добавлять членов в класс, кроме как между фигурными скобками определения класса.
  • 1
    В долгосрочной перспективе 1. будет предпочтительнее взломов / уловок, которые также сделают ваш код менее читабельным
Показать ещё 2 комментария
Теги:

3 ответа

2

Простым способом может быть вывод собственного класса из класса библиотеки и повторное добавление к нему всех функций старой версии. Это не требует написания полного адаптера и не касается кода библиотеки. Вам просто нужно переименовать переименование для имени класса, которое менее подвержено ошибкам и масштабируется лучше.

0

Я считаю, что это хорошо подходит для Политики.

Вы можете определить два интерфейса:

class A {
    void fnOldFunction();
public:
    void fn() {
        fnOldFunction();
    }
};
class B {
    void fnNewFunction();
public:
    void fn() {
        fnFunction();
    }
};

A и B могут наследовать классы старой/новой библиотеки. Теперь вам просто нужно определить свой рабочий класс следующим образом:

template <typename Policy>
class C : public Policy {
    /* Whatever you need */
public:
    /* Say doSomething need to call fn */
    void doSomething() {
        /* Whatever */
        fn();
        /* ... */
    }
};

Теперь, в зависимости от вашего usecase, вы можете использовать C<A> или C<B>. Обратите внимание, что это может быть громоздким, если многие имена изменились в библиотеке (нарушение API, как будто это не очень хорошая идея, у вас есть мое сочувствие :().

С этим решением, которое в терминах почти то же, что и @Alexander, вы все равно можете ссылаться на старую библиотеку, а также на новую версию. Вам просто нужно переключиться с C<B> на C<A>.

Вы могли бы даже связать это с другими методами метапрограммирования, такими как черты типа, чтобы заставить компилятор вывести, если вам нужно C<A> или C<B> самостоятельно. Если возможно, вам даже не придется прикасаться к коду для компиляции с любой версией lib.

0

Вы можете использовать макрос для этой породы.

class A {
public:
  void fnNewFunction() {}
};

int main(void) {
  A a;
  a.fnNewFunction();

#define fnOldFunction fnNewFunction

  a.fnOldFunction();
}

Я не советую использовать эту технику. Это приведет к зависанию intellisense и может привести к ошибкам (что, если есть другой класс с определенными fnOldFunction и fnNewFunction?)

Причина, по которой я написал это, заключается в том, что она отвечает на ваш конкретный вопрос.

Предпочтительным вариантом является вариант 1. Вы можете легко использовать средства рефакторинга вашего редактора для немедленного выполнения этого действия.

Ещё вопросы

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