假设我们有一个单独的整数列表,我们给出了以下要求:
可能的解决方案如下:
struct node {
int data;
node *next;
};
void insertBeginning(node **list, int data)
{
node *n = new node;
n->data = data;
n->next = *list;
*list = n;
}
void option1(node *node)
{
if (node != NULL) {
cout << node->data << endl;
option1(node->next);
}
}
void option2(node *node)
{
if (node != NULL) {
if (node->data % 2 == 0)
cout << node->data << endl;
option2(node->next);
}
}
void option3(node *node)
{
if (node != NULL) {
if (node->data % 3 == 0)
cout << node->data << endl;
option3(node->next);
}
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
option1(root);
cout << endl;
cout << "OPTION 2" << endl;
option2(root);
cout << endl;
cout << "OPTION 3" << endl;
option3(root);
}
但仔细观察发现,在每个菜单选项中都有一个循环遍历节点的算法,在所有选项中都是相同的,然后是特定的操作。因此,将循环算法与动作分开可能是件好事。你会怎么做?
在这种情况下,循环算法以及操作非常简单,因此进行分离将是杀手锏,但在我的情况下,循环算法和操作更复杂,我想避免复制和粘贴循环算法。此外,这种情况使用单链表,但它可能是一棵树。无论如何,我不想用这些细节分散你的注意力。
最后考虑第四种选择:
可能的解决方案如下:
void loopNodes(node * n, void action(node * n))
{
if (n != NULL) {
action(n);
loopNodes(n->next, action);
}
}
void option1(node * node)
{
cout << node->data << endl;
}
void option2(node * node)
{
if (node->data % 2 == 0)
cout << node->data << endl;
}
void option3(node * node)
{
if (node->data % 3 == 0)
cout << node->data << endl;
}
int sum;
void option4(node * node)
{
sum += node->data;
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
loopNodes(root, option1);
cout << endl;
cout << "OPTION 2" << endl;
loopNodes(root, option2);
cout << endl;
cout << "OPTION 3" << endl;
loopNodes(root, option3);
cout << endl;
cout << "OPTION 4" << endl;
sum = 0;
loopNodes(root, option4);
cout << "SUM = " << sum << endl;
}
选项4引入了挑战;需要保持状态。我使用了一个带有文件范围的变量,但另一种选择可能是(这是我的最终解决方案):
void loopNodes(node * n, void action(node * n, void *state), void *state)
{
if (n != NULL) {
action(n, state);
loopNodes(n->next, action, state);
}
}
void option1(node * node, void *state)
{
cout << node->data << endl;
}
void option2(node * node, void *state)
{
if (node->data % 2 == 0)
cout << node->data << endl;
}
void option3(node * node, void *state)
{
if (node->data % 3 == 0)
cout << node->data << endl;
}
void option4(node * node, void *state)
{
*(int *) state += node->data;
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
loopNodes(root, option1, NULL);
cout << endl;
cout << "OPTION 2" << endl;
loopNodes(root, option2, NULL);
cout << endl;
cout << "OPTION 3" << endl;
loopNodes(root, option3, NULL);
cout << endl;
cout << "OPTION 4" << endl;
int *sum = new int;
*sum = 0;
loopNodes(root, option4, sum);
cout << "SUM = " << *sum << endl;
}
您怎么看?
非常感谢任何反馈!
注意:我必须使用核心语言工具(我不能使用标准库,提升等)。
答案 0 :(得分:0)
就OOP而言,您的选项机制取决于绑定到每个选项输入的某些特定处理,在这种情况下是正整数。您可以考虑使用Handle类在构造期间接受两个输入,一个是选项号(即整数),第二个是lambda函数或应用逻辑的函数指针。然后,您的链接列表可以使用AssignHandles()方法自动构建菜单行为。
答案 1 :(得分:0)
您可以将模板化版本用于循环功能。这可以与函数或函数对象一起使用,它们实现operator():
#include <iostream>
int list[] = {1, 2, 3, 4, 5};
template<class Option>
void loop(Option & option) {
for (size_t i = 0; i < sizeof(list)/sizeof(list[0]); ++i) {
option(list[i]);
}
}
void print(int e) {
std::cout << e << std::endl;
}
struct Sum {
int sum = 0;
void operator () (int e) {
sum += e;
}
};
int main(int argc, char** argv) {
loop(print);
Sum s;
loop(s);
std::cout << s.sum << std::endl;
return 0;
}