У меня есть функция User::func()
(callback), которая будет вызвана классом шаблона (Library<T>
).
На первой итерации развития все знают, что func()
служит только для этой единственной цели.
Несколько месяцев спустя большинство членов забывают, что такое func()
.
После некоторого тяжелого рефакторинга, func()
иногда удаляется некоторыми кодировщиками.
Сначала я не думал, что это проблема вообще.
Однако после того, как я несколько раз столкнулся с этим шаблоном, мне кажется, что мне нужна контрмера.
Вопрос
Как оформлять его элегантно? (cute && сжатие && no дополнительные затраты ЦП)
Пример
Вот упрощенный код: -
(Реальная проблема заключается в рассеянии около 10+ библиотечных файлов и 20 + пользовательских файлов и более 40 функций.)
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
node->func(); //#1
}
};
user.h
class User{
public: void func(){/** some code*/} //#1
//... a lot of other functions ...
// some of them are also callback of other libraries
};
main.cpp
int main(){
Library<User> li; .... ; li.utility();
}
Мои плохие решения
1. Комментарий /doc
В качестве первого обходного пути я хотел бы добавить комментарий следующим образом: -
class User{
/** This function is for "Library" callback */
public: void func(){/** some code*/}
};
Но он становится грязным довольно быстро - я должен добавить его к каждому "func" в каждом классе.
2. Переименуйте "func()"
В реальном случае я предпочитаю префикс имени функции следующим образом: -
class User{
public: void LIBRARY_func(){/** some code*/}
};
Это очень заметно, но имя функции теперь очень велико.
(особенно когда Library
-класс имеет более длинное имя класса)
3. Виртуальный класс с "func() = 0"
Я рассматриваю возможность создания абстрактного класса в качестве интерфейса для обратного вызова.
class LibraryCallback{
public: virtual void func()=0;
};
class User : public LibraryCallback{
public: virtual void func(){/** some code*/}
};
Он обеспечивает ощущение, что func()
для что-то-довольно-внешнего. :)
Тем не менее, я должен пожертвовать стоимостью виртуального вызова (v-table).
В критичных по производительности случаях я не могу себе этого позволить.
4. Статическая функция
(идея от Дэниела Жора в комментарии, спасибо!)
Почти через месяц, вот как я использую: -
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
T::func(node); //#1
}
};
user.h
class User{
public: static void func(Callback*){/** some code*/}
};
main.cpp
int main(){
Library<User> li;
}
Это, вероятно, более чистый, но все еще не хватает самодокумента.