#c #qt #callback #void #point-cloud-library
#c #qt #обратный вызов #пустота #точка-облако-библиотека
Вопрос:
Я объявляю конкретную функцию обратного вызова клавиатуры как это в моем коде:
void keyboardEventCallback(const pcl::visualization::KeyboardEvent amp;event, void* viewer_void, void* widget_void);
Событие клавиатуры — это фактическое событие, переданное функции обратного вызова, параметр viewer_void — это указатель на класс PCLVisualizer, который генерирует окно для рендеринга, а widget_void — это указатель на виджет, который взаимодействует с Qt.
В документации для pcl функция регистрации передает аргументы для регистрации функции клавиатуры, например
boost::signals2::connection registerKeyboardCallback(void(T::*callback)(const pcl::visualization::KeyboardEventamp;, void*), Tamp; instance, void* cookie=nullptr)
Итак, мой вопрос в том, что означает T::*
внутри объявления функции регистрации, и почему мне не разрешено передавать это:
m_vis->registerKeyboardCallback(keyboardEventCallback, (void*)amp;m_vis, (void*)this);
где m_vis
это визуализатор, keyboardcallback
это обратный вызов, а это виджет.
Почему я не могу зарегистрироваться таким образом. Это для библиотеки облака точек.
Ответ №1:
что означает T::* внутри объявления функции регистрации
Это синтаксис указателя на элемент. Давайте посмотрим на полный тип и имя параметра:
void(T::*callback)(const pcl::visualization::KeyboardEventamp;, void*)
Это объявление переменной с именем callback
. Это указатель на функцию-член. Точнее, это указатель на функцию-член класса T
.
Если мы уберем имя из типа, мы увидим вещи более четко:
// class name ---v v------- parameters
void(T::*)(const pcl::visualization::KeyboardEventamp;, void*)
// ^---- return type
На самом деле это указатель на функцию-член класса, T
который возвращает void
. Это функция, которая принимает строго два параметра: a const pcl::visualization::KeyboardEventamp;
и a void*
.
почему мне не разрешено передавать это
Это просто. Посмотрите на тип вашей функции:
using func_type = decltype(keyboardEventCallback);
// hint: the type is: void(*)(const pcl::visualization::KeyboardEventamp;, void*, void*)
Давайте сравним два типа параллельно:
void(*)(const pcl::visualization::KeyboardEventamp;, void*, void*)
void(T::*)(const pcl::visualization::KeyboardEventamp;, void*)
Во-первых, ваша функция не является функцией-членом, это простой указатель на функцию. Это не тот же тип. Тогда у вас есть три аргумента, поскольку тип параметра запрашивает только два. Это другое.
Теперь, как вы можете это исправить??
Вы могли бы использовать лямбда:
auto myCallback = [](const pcl::visualization::KeyboardEventamp; e, void* c) { /* ... */ }
using lambdaType = decltype(myCallback);
// Be careful here, we don't want our lambda to go out of scope when it is called.
m_vis->registerKeyboardCallback(amp;lambdaType::operator(), myCallback, this);
Или еще проще: просто определите keyboardEventCallback
внутри вашего класса и отправьте его:
// don't forget: keyboardEventCallback must receive the same parameter as asked.
m_vis->registerKeyboardCallback(amp;MyClass::keyboardEventCallback, *this, this);
Ответ №2:
Это синтаксис для функций-членов.
Пример:
class A{
int giveMe5();
};
amp;A::giveMe5; // will be of type int(A::*)()
Почему тип отличается от свободных функций и статических функций-членов?
Потому что функции-члены имеют неявный параметр, который указывает на объект, для которого вызывается функция.
https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types говорит:
Тип этой функции отличается в зависимости от того, является ли это обычной функцией или нестатической функцией-членом некоторого класса:
— Его тип —
int (*)(char,float)
если обычная функция— Его тип —
int (Fred::*)(char,float)
если нестатическая функция-член класса Fred
Комментарии:
1. Это очень ценная дополнительная информация! Было бы полезно, если бы вы скопировали и заключили в кавычки (с
> my quote
) содержимое ссылки вместо того, чтобы просто ссылаться на нее. Даже скриншот может быть в порядке, хотя в этом случае цитирование является лучшим и не сложным.