Что означает T::* при объявлении списка параметров функции?

#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 ) содержимое ссылки вместо того, чтобы просто ссылаться на нее. Даже скриншот может быть в порядке, хотя в этом случае цитирование является лучшим и не сложным.