У меня есть большое приложение C++, которое использует старую версию библиотеки с открытым исходным кодом. Я хочу перейти на новую библиотеку. В новой библиотеке старая функция fnOldFunction() удаляется и добавляется новая функция fnNewFunction(). Теперь у меня есть два варианта:
Замените все экземпляры fnOldFunction() на fnNewFunction(). У меня есть много других функций, таких как fnOldFunction(), я не хочу иметь дело с n функциями с тысячами находок и заметок.
У меня есть исходный код библиотеки. Я могу добавить fnOldFunction() и вызвать fnNewFunction из fnOldFunction(). Но даже у меня есть исходный код этого libray, не хочу вносить какие-либо изменения в исходный код libray.
Может ли кто-нибудь дать мне другой способ добиться того же. Я знаю, что некоторые языки, такие как Ruby, Javascript, Objective C, предоставляют возможность расширения/изменения существующего класса без изменения исходного кода этого класса. Но C++ не хватает этой возможности.
Простым способом может быть вывод собственного класса из класса библиотеки и повторное добавление к нему всех функций старой версии. Это не требует написания полного адаптера и не касается кода библиотеки. Вам просто нужно переименовать переименование для имени класса, которое менее подвержено ошибкам и масштабируется лучше.
Я считаю, что это хорошо подходит для Политики.
Вы можете определить два интерфейса:
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.
Вы можете использовать макрос для этой породы.
class A {
public:
void fnNewFunction() {}
};
int main(void) {
A a;
a.fnNewFunction();
#define fnOldFunction fnNewFunction
a.fnOldFunction();
}
Я не советую использовать эту технику. Это приведет к зависанию intellisense и может привести к ошибкам (что, если есть другой класс с определенными fnOldFunction
и fnNewFunction
?)
Причина, по которой я написал это, заключается в том, что она отвечает на ваш конкретный вопрос.
Предпочтительным вариантом является вариант 1. Вы можете легко использовать средства рефакторинга вашего редактора для немедленного выполнения этого действия.