使用指向成员函数的指针来确定调用哪个函数

久保

我有以下课程:

class Karen
{
    public:
        Karen(void);
        ~Karen(void);

        void complain(std::string level);

    private:
        void    debug(void)     const;
        void    info(void)      const;
        void    warning(void)   const;
        void    error(void)     const;
};

complain函数接收一个字符串,其中可以包含 debug、info、warning 或 error 等词,并且它必须在不使用 if/elseif/else 森林的情况下调用适当的函数,而是使用指向成员函数的指针。的原型complain是给我的。我是成员函数指针的新手,我不确定如何管理它。我的尝试之一是这样的:

void    Karen::complain(std::string level)
{

    std::string     *p = &level;
    void            (Karen::*f)(void)       const;

    (this->*(*p))();
}

最后一行的语法不正确,但我正在尝试这样做,但我(this->*(content of pointer p))()不知道如何编写。有人能帮我吗?

编辑我只允许使用 C++98

463035818_is_not_a_number

通过成员函数指针调用成员函数的语法是

(this->*memf)();

您不能神奇地将字符串转换为成员函数指针。马虎地说,运行时不存在函数名称。如果你想要这样的映射,你需要自己提供。没办法。您可以通过使用以下命令来避免“if-else 森林” std::unordered_map

#include <unordered_map>
#include <string>
#include <iostream>

class Karen
{
    public:
        void complain(std::string level) {
            static const std::unordered_map<std::string, void(Karen::*)() const>  m{
                {"debug",&Karen::debug},
                {"info",&Karen::info},
                {"warning",&Karen::warning},
                {"error",&Karen::error}
            };
            auto it = m.find(level);
            if (it == m.end()) return;
            (this->*(it->second))();
        }

    private:
        void debug(void) const { std::cout << "debug\n"; }
        void info(void) const { std::cout << "info\n"; }
        void warning(void) const { std::cout << "warning\n"; }
        void error(void) const { std::cout << "error\n"; }
};

int main() {
    Karen k;
    k.complain("info");
}

现场演示

如评论中所述,您可以使用枚举代替字符串。如果可能,您应该使用编译器的帮助,它可以诊断枚举中的拼写错误,但不能诊断字符串中的拼写错误。或者,您可以直接将成员函数指针传递给complain. 那么实现complain将是微不足道的,不需要分支。尽管这将要求方法是公开的,并且调用者必须处理成员函数指针。


如果你不被允许使用 C++11 或更高版本,你应该和你的老师认真谈谈。很快 C++20 将成为事实上的标准,并且情况发生了很大变化。我不再精通 C++98,所以这里只是对上述内容的快速修复,以使其以某种方式工作。您不能使用std::unordered_map但是有std::map并且地图的初始化相当麻烦:

#include <map>
#include <string>
#include <iostream>

class Karen
{
    typedef void(Karen::*memf_t)() const; 
    typedef std::map<std::string,void(Karen::*)() const> map_t;

    public:
        void complain(std::string level) {
            map_t::const_iterator it = get_map().find(level);
            if (it == get_map().end()) return;
            (this->*(it->second))();
        }

    private:
        const map_t& get_map(){
            static const map_t m = construct_map();
            return m;
        }
        const map_t construct_map() {
            map_t m;
            m["debug"] = &Karen::debug;
            m["info"] = &Karen::info;
            m["warning"] = &Karen::warning;
            m["error"] = &Karen::error;
            return m;
        }
        void debug(void) const { std::cout << "debug\n"; }
        void info(void) const { std::cout << "info\n"; }
        void warning(void) const { std::cout << "warning\n"; }
        void error(void) const { std::cout << "error\n"; }
};

int main() {
    Karen k;
    k.complain("info");
}

现场演示

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章