C++ 函数作为具有默认值的参数

C++ 函数作为具有默认值的参数,c++,function-pointers,C++,Function Pointers,我想为二叉树创建一个类: struct TreeNode { explicit TreeNode(int _value) : value(_value) {} int value = 0; TreeNode* left = nullptr; TreeNode* right = nullptr; }; class BTree { public: void Add(int value); void PrintPostOrde

我想为二叉树创建一个类:

struct TreeNode {
    explicit TreeNode(int _value) : value(_value) {}

    int value = 0;
    TreeNode* left = nullptr;
    TreeNode* right = nullptr;
};

class BTree {
    public:
        void Add(int value);
        void PrintPostOrder(void (*func)() = print_current);
        ~BTree();

    private:
        TreeNode* root = nullptr;    
        void print_current();
        void delete_node();
};

BTree::~BTree() {
    PrintPostOrder(delete_node);
}
我的想法-对于析构函数和打印,我需要进行二叉树遍历。因此,我想创建函数遍历,并将
函数
用作其中的参数: 如果需要打印
func=print
,对于析构函数
func=delete\u节点

此处有错误:

void PrintPostOrder(void (*func)() = print_current);
类型为“void(BTree::)()”的默认参数不兼容 使用类型为“void()()”的参数


当参数是一个函数时,我不知道如何设置参数的默认值。

原则上,您可以像以前那样为函数设置默认参数。问题是成员函数与自由函数的类型不同

这是一个自由函数指针
void(*func)(
),而
print\u current
是类型为
void(BTree::)()
的成员函数

修复参数类型或使用自由函数作为默认参数


另外,不要忘记成员函数与自由函数有着本质的区别,因为您需要一个实例来调用它们。

原则上,您可以像以前那样为函数设置默认参数。问题是成员函数与自由函数的类型不同

这是一个自由函数指针
void(*func)(
),而
print\u current
是类型为
void(BTree::)()
的成员函数

修复参数类型或使用自由函数作为默认参数


另外,不要忘记成员函数与自由函数有本质的区别,因为您需要一个实例来调用它们。

print\u current
delete\u node
都是成员函数,因此您需要一个成员函数指针:

class BTree {
public:
    void PostOrder(void (BTree::*fn)() = &BTree::print_current) {
        std::invoke(fn, this);
    }

    ~BTree() {
        PostOrder(&BTree::delete_node);
    }

private:
    void print_current();
    void delete_node();
};
为了获得更大的灵活性,您可以将
PostOrder
作为模板:

struct TreeNode {};

class BTree {
public:
    template<class Fn>
    void PostOrder(Fn fn) { 
        std::invoke(fn);
    }

    void PostOrder() {
        PostOrder([this] { print_current(); });
    }

    ~BTree() {
        TreeNode* node;
        PostOrder([this, node] { delete_node(node); });
    }

private:
    void print_current();
    void delete_node(TreeNode*);
};
struct TreeNode{};
B类树{
公众:
模板
无效后序(Fn-Fn){
调用(fn);
}
作废邮购(){
后序([this]{print_current();});
}
~b树(){
TreeNode*节点;
后序([this,node]{delete_node(node);});
}
私人:
无效打印_当前();
void delete_节点(TreeNode*);
};

print\u current
delete\u node
是成员函数,因此需要成员函数指针:

class BTree {
public:
    void PostOrder(void (BTree::*fn)() = &BTree::print_current) {
        std::invoke(fn, this);
    }

    ~BTree() {
        PostOrder(&BTree::delete_node);
    }

private:
    void print_current();
    void delete_node();
};
为了获得更大的灵活性,您可以将
PostOrder
作为模板:

struct TreeNode {};

class BTree {
public:
    template<class Fn>
    void PostOrder(Fn fn) { 
        std::invoke(fn);
    }

    void PostOrder() {
        PostOrder([this] { print_current(); });
    }

    ~BTree() {
        TreeNode* node;
        PostOrder([this, node] { delete_node(node); });
    }

private:
    void print_current();
    void delete_node(TreeNode*);
};
struct TreeNode{};
B类树{
公众:
模板
无效后序(Fn-Fn){
调用(fn);
}
作废邮购(){
后序([this]{print_current();});
}
~b树(){
TreeNode*节点;
后序([this,node]{delete_node(node);});
}
私人:
无效打印_当前();
void delete_节点(TreeNode*);
};

太棒了!我得到了它。我可以再问一个问题吗:如果
delete\u node
函数有一个参数(指向要删除的节点的指针),但
print\u current
没有,该怎么办。我如何将函数作为参数提取,而它可能有参数,也可能没有参数?@Mikhail_Sam,最简单的解决方案是将其作为模板。@Evg看起来是另一个大问题。谢谢大家!@Mikhail_Sam在这种情况下,我会将两者包装在一个不带参数的lambda中。当然,这取决于您在什么时候知道要传递的参数。也许最好打开另一个问题(以防你在别处找不到答案)太棒了!我得到了它。我可以再问一个问题吗:如果
delete\u node
函数有一个参数(指向要删除的节点的指针),但
print\u current
没有,该怎么办。我如何将函数作为参数提取,而它可能有参数,也可能没有参数?@Mikhail_Sam,最简单的解决方案是将其作为模板。@Evg看起来是另一个大问题。谢谢大家!@Mikhail_Sam在这种情况下,我会将两者包装在一个不带参数的lambda中。当然,这取决于您在什么时候知道要传递的参数。也许最好打开另一个问题(以防你在别处找不到答案)请不要垃圾邮件标签,你的代码是关于一棵树的,但问题与此无关。我更改了标签,如果您不满意,请重新更改(fwiw,我没有添加
成员函数指针
标签,因为当标签已经有一半答案时,我总是觉得很奇怪)请不要垃圾标签,您的代码是关于树的,但问题与此无关。我更改了标记,如果您不满意,请将其更改回来(fwiw,我没有添加
成员函数指针
标记,因为当标记已经有一半答案时,我总是觉得很奇怪)我可以使用
void(BTree::*func)(=print\u current
还是需要使用
void(BTree::*func)(=&print\u current)
?或者
void(BTree::*func)(=&BTree::print_current)
?@Mikhail_Sam,不幸的是,它应该是如此冗长,
&BTree:>print_current
。我认为
printpostore
应该被命名为
posterorder
。我可以使用
void(BTree:*func)(=print_current
,或者我需要使用
void(BTree:*func)()=&print_current)
?或者
void(BTree::*func)(=&BTree::print_current)
?@Mikhail_Sam,不幸的是,它应该是如此冗长,
&BTree::print_current
。我认为
printpostore
应该被命名为
postore