这是一个有点标准的链接列表练习。我有一个函数,它接受另一个函数并循环遍历列表,特别是_node_loop
。为什么我使用的语法有效?我还没有看到看起来像它的函数指针语法。
为方便测试而包含完整的代码,但我的问题是关于函数_node_loop
,_del_node
和_print_node
。
#include<stddef.h>
#include <iostream>
template <class T>
class Node {
public:
T value;
Node<T>* next;
Node(T value_, Node<T>* next_) : value(value_), next(next_) {}
Node(T value_) : value(value_), next(NULL) {}
};
using namespace std;
template <class T>
class List {
public:
List() : head(NULL) {}
void prepend(T val) {
Node<T>* node_ptr = new Node<T>(val, head);
head = node_ptr;
}
void print() {
cout << "[";
_node_loop(_print_node);
cout << "]" << endl;
}
~List() {
_node_loop(_del_node);
}
static List<T> from_array(T tarray[], int N) {
List<T> ls = List<T>();
for (int i = 0; i < N; i++) {
ls.prepend(tarray[i]);
}
return ls;
}
private:
Node<T>* head;
void _node_loop(void kernel(Node<T>*)) {
Node<T>* node_ptr = head;
Node<T>* tmp;
while (node_ptr != NULL) {
tmp = node_ptr;
node_ptr = node_ptr->next;
kernel(tmp);
}
}
static void _print_node(Node<T>* node_ptr) {
if (node_ptr->next == NULL) {
cout << node_ptr->value;
}
else {
cout << node_ptr->value << ", ";
}
}
static void _del_node(Node<T>* node_ptr) {
delete node_ptr;
}
};
int main() {
int my_array[] = {1, 2, 3, 4, 5};
List<int> my_list = List<int>::from_array(my_array, 5);
my_list.print();
return 0;
}
答案 0 :(得分:1)
我会对我的评论进行一些扩展。
在解析函数声明后直接调整(或衰减)函数参数类型:
some_type
数组已调整为指针some_type
some_type
的函数调整为指向返回some_type
的函数的指针 int const
- &gt; int
)见[dcl.fct] / 5;保留函数类型的参数,即指向函数的指针包含与原始函数类型相同的参数。
此调整仅在 函数参数类型中进行。它反映了一些可以应用于表达式的隐式转换:
some_type
的一个(左值)数组可以转换为指向some_type
的指针,指向数组的第一个元素(“array-to-pointer conversion”,[conv.array])some_type
可以转换为指向函数返回some_type
(“函数到指针”转换“,[conv.func])int
到const int
[conv.qual] 函数类型与函数指针类型不同,但两者都与数组和指针类似。例如,您可以使用函数类型声明(但不定义)函数:
typedef void my_function_type(int, double);
my_function_type f0; // declare the function `void f0(int, double)`
my_function_type f1; // declare the function `void f1(int, double)`
int main()
{
f0(42, 1.2);
f1(42, 1.2);
}
#include <iostream>
void f0(int, double) { std::cout << "f0\n"; }
// illegal:
//my_function_type f1 { std::cout << "f1\n"; }
void f1(int, double) { std::cout << "f1\n"; }
您可以使用函数类型:
来获取函数的引用和指针my_function_type& my_ref = f0;
my_function_type* my_ptr = f1;
在最后一行中,使用了函数到指针的转换。它相当于:
my_function_type* my_ptr = &f1;
调用函数指针不需要使用一元*
。这是语法糖,因为它的含义是明确的,例如
my_ptr(42, 3.14);
因此,以下所有条款均有效:
my_ptr(42, 3.14);
(*my_ptr)(42, 3.14);
my_ref(42, 3.14);
f0(42, 3.14);
N.B。 ()
(函数调用)的优先级高于一元*
,因此*my_ptr
周围的括号是必需的。
由于一元*
需要指针类型,您可以根据需要添加任意数量*
,请参阅Why do all these crazy function pointer definitions all work? What is really going on?
void _node_loop(void kernel(Node<T>*));
此名为_node_loop
的成员函数返回void
并采用类型为void(Node<T>*)
的参数。此参数类型调整为void (*) (Node<T>*)
,因此_node_loop
的声明等同于:
void _node_loop(void (*kernel)(Node<T>*));
在此函数中,使用参数kernel
:
kernel(tmp);
我们可以通过函数指针调用函数而不使用*
。但我们可以更明确(我不推荐):
(*kernel)(tmp);