Я разрабатываю шаблонное дерево двоичного поиска в C++ для класса структур данных прямо сейчас. До сих пор все шло хорошо. Эта проблема связана с некоторыми nitty gritty C++, с которыми мне не знакомы, и мне нужна помощь.C++ function pointer casting
Я ранее определял функции, которые пересекают дерево и посещают каждый узел в разных порядках. Здесь речь идет о следующем.
TreeNode.h
public:
static void PostOrderVisit(TreeNode<T>* node, void visit(const T& v));
TreeNode.cpp
template <class T> void TreeNode<T>::PostOrderVisit(TreeNode* node, void visit(const T& v)) {
if (node->leftChild != NULL)
PostOrderVisit(node->leftChild, visit);
if (node->rightChild != NULL)
PostOrderVisit(node->rightChild, visit);
visit(node->value);
}
Это прекрасно работает в тестовой программе, которая делает узлы и статически вызывает PostOrderVisit.
В классе friend (BinSTree.h/cpp) я реализую метод, который удаляет каждый узел в дереве, поэтому я подумал, что было бы неплохо использовать этого посетителя и вызвать функцию Delete() каждый узел (функция Delete() также отлично работает в тестовых программах для BinSTree).
Эта функция определяется следующим образом.
template <class T> void BinSTree<T>::ClearTree() {
TreeNode<T>::PostOrderVisit(this->root(), &BinSTree<T>::Delete);
}
И здесь проблема. г ++ говорит ...
BinSTree.cpp:156: error: no matching function for call to ‘TreeNode<int>::PostOrderVisit(TreeNode<int>*, void (BinSTree<int>::*)(const int&))’
TreeNode.cpp:56: note: candidates are: static void TreeNode<T>::PostOrderVisit(TreeNode<T>*, void (*)(const T&)) [with T = int]
В этом случае, я думал, что void (BinSTree<T>::*)(const T&)
будет экземпляром void (*)(const T&)
, но это не так. Единственный способ, которым я могу получить вызов распознаваться определения функции литьем указатель на функцию, как это:
TreeNode<T>::PostOrderVisit(this->root(), (void (*)(const T& v)) &BinSTree<T>::Delete);
Это признает функцию и называет ее соответствующим образом, однако (это потребовалось некоторое значительное исследование ...), Функции-члены C++ имеют неявный параметр, который позволяет получить доступ к этому ключевому слову изнутри. Приведение указателя функции-члена к указателю простой функции полностью сбрасывает эту ссылку, заставляя метод Delete() выполнить seg fault (он использует это «совсем немного»).
Это был ХАЛ от хлопот, и я потратил немало времени на такую небольшую часть этого проекта. Может ли кто-нибудь показать мне способ либо A: сделать функцию признанной без кастинга, либо B: как поддерживать «эту» ссылку во время трансляции. Методы ClearTree() и Delete() находятся в одном классе.
Заранее спасибо.
Если вы уже используете шаблоны, пропустите указатели на функции и перейдите непосредственно к функторам. Не виртуальные вызовы с неинтерфейсом могут быть встроены. Сделайте 'посещение' шаблон, который может перегрузить' operator()() '. – asveikau