C++ 试图避免重复调用函数

C++ 试图避免重复调用函数,c++,member-function-pointers,boost-preprocessor,C++,Member Function Pointers,Boost Preprocessor,我有一个非常简单的类定义,如下所示: #include "../bshttp/controllers.h" #include <iostream> #include <string> class DerivedController : public BS_Controllers { public: DerivedController():BS_Controllers(this) { m_urlRules["print"] = REG_

我有一个非常简单的类定义,如下所示:

#include "../bshttp/controllers.h"
#include <iostream>
#include <string>

class DerivedController : public BS_Controllers
{
  public:
    DerivedController():BS_Controllers(this)
    {
        m_urlRules["print"] = REG_NAME &DerivedController::print;
        //regController(REG_NAME &DerivedController::print,"print");
        regController(REG_NAME &DerivedController::printView,"printView");
    }
    void * print()
    {
        return NULL;
    }
    void * printView()
    {
        cout<<"Print view!"<<endl;
        return NULL;
    }
};

必须为所有成员函数调用。它所做的就是获取类的成员函数指针,并用字符串映射,以便以后可以用字符串标识函数

一切都很好并且正常工作,但是当类结构变大时,程序员将不得不为每个成员函数重复调用这个函数。是否需要使用预处理器或任何预处理库(如boost wave),这样程序员就不必重复调用

编辑: 很抱歉造成混淆,我在这里显然没有很好地描述这个问题。 我将字符串映射到成员函数指针

m_urlRules是一个std::map,字符串作为键,成员函数指针作为值 regController基本上是m_urlRules的setter函数,因此这两个语句有效地执行相同的操作,将字符串映射到成员函数

REG_NAME是一个宏,用于替换非常难看的类型转换

我想做的是,如果类的结构如下

class DerivedController : public BS_Controllers
{
  public:
    DerivedController():BS_Controllers(this);
    void * print();
    void * print2();
    void * print3();
    void * print4();
};
我不必在构造函数中执行以下操作:

 m_urlRules["print"] = REG_NAME &DerivedController::print;
 m_urlRules["print1"] = REG_NAME &DerivedController::print1;
 m_urlRules["print2"] = REG_NAME &DerivedController::print2;
 m_urlRules["print3"] = REG_NAME &DerivedController::print3;
 m_urlRules["print4"] = REG_NAME &DerivedController::print4;

我不确定我是否完全理解了您的问题,但是为什么不使用内置的数据结构,例如map,在其中可以将它映射到键(字符串)


我相信您希望使用此功能记录日志,以查看出现问题的地方

我想你在寻找这样的东西:

urlRules     ("<function name>");
regController("<function name>");
注意:我没有测试它,它可能不工作,但在我的理解它应该

编辑

现在我明白了,你想要调用构造函数中的每个函数。 实际上,构造函数是错误的位置,因为它会为您创建的每个对象调用,但您只需分配一次指针。(例如启动时)

看,一个类的函数在内存中只存在一次,连接到指针的是yield数据,所以所有的成员变量

很抱歉,没有简单的方法可以按名称获取所有类成员,然后对其进行检查。 至少据我所知不是这样

但是您应该记住,对于任何给定的对象,函数指针都不会改变。
做这项工作的外部功能会更智能。启动时调用。

嗯,您正在尝试自己构建运行时类型信息(RTTI),因此没有用于此操作的预处理器宏。主要是因为预处理器宏扩展到一个地方,而声明函数的地方和注册函数的地方是不同的


Qt和qmake执行类似的操作,它查找标记为signals/slot的函数,并为RTTI构建一个moc对象。这是你可以用C++得到的最好的。其他语言如java和Delphi,比C++有更多的RTI,并使它能够在运行时查询函数。

< P>我将首先去除丑陋的类型(即使在宏表单中)。这可以通过将
m_urlRules
BS_Controllers
移动到中间(或代理)模板类中来实现。该模板用于将映射解析为正确的派生类型。(我不知道您是如何定义BS_控制器的,所以我编了一个。)

您可以查看上述代码的一部分

如果要使填充半自动,还必须在某个地方定义方法列表。你可以把它们列在一个文件里

// DerivedController rules
DERIVED_RULE_INC(print)
DERIVED_RULE_INC(printView)
//...
然后将
DerivedController
类更改为使用此文件:

class DerivedController : public BS_Proxy<DerivedController> {
    struct Populate {
        Populate () {
            #define DERIVED_RULE_INC(x) REG_RULE(DerivedController, x);
            #include "derived_controller_rules.inc"
            #undef DERIVED_RULE_INC
        }
    };
public:
    DerivedController() {
        static Populate populate_;
    }
    #define DERIVED_RULE_INC(x) void * x ();
    #include "derived_controller_rules.inc"
    #undef DERIVED_RULE_INC
};

void * DerivedController::print() { return NULL; }

void * DerivedController::printView() {
    std::cout<<"Print view!"<<std::endl;
    return NULL;
}
类派生控制器:公共BS_代理{
结构填充{
填充(){
#定义派生规则(x)注册规则(DerivedController,x);
#包括“派生控制器规则公司”
#未定义派生规则公司
}
};
公众:
DerivedController(){
静态填充;
}
#定义派生规则INC(x)void*x();
#包括“派生控制器规则公司”
#未定义派生规则公司
};
void*DerivedController::print(){return NULL;}
void*DerivedController::printView(){

std::coutIt似乎你是在用一种想象的方式来描述一个问题,而不是描述某件事——这是什么?
m_rlrules
regController
定义在哪里以及如何定义的?
REG_NAME
是一个进行某种类型转换的宏吗?
m_rlrules
是一个std::映射,用于字符串到成员函数pointers.
regController
基本上是一个映射的设置器,它做着完全相同的事情。
regu NAME
是一个类型转换宏,因为它不能很好地描述这个问题。m_urlRules已经是一个std::mapYes,我正在尝试做的是基本上RTTI,但我所需要的只是该映射的成员函数名和成员函数指针e类,这就是我正在尝试做的。qt方法是为每个Q_对象类为RTTI生成一个单独的文件。qmake处理该文件并侦听Q_对象、信号和插槽等qt宏,然后构建该文件。这是您能得到的最好结果,因为它是完全自动的。您应该尝试相同的方法。它需要一个最小的解析器,witch只理解基本的类语法。你甚至可以跳过大多数宏,但你需要像Q_OBJECTQ_OBJECT这样的东西。Q_OBJECT是最合理的选择,只是因为我自己的原因尽量避免使用Qt库。你是对的,外部调用会更好。但更重要的是,我试图找到一个自动的方法我想添加所有这些函数。我想我运气不好。。
m_urlRules["<function name>"] = REG_NAME &DerivedController::print;
regController(REG_NAME &DerivedController::printView,"<function name>");
#define      urlRules(x) { m_urlRules[(x)] = REG_NAME &DerivedController::print; }
#define regController(x) { regController(REG_NAME &DerivedController::printView,(x)); }
class BS_Controllers {
protected:
    virtual ~BS_Controllers () {}
public:
    virtual void * invokeRule (const std::string &) = 0;
};

template <typename D>
class BS_Proxy : public BS_Controllers {
    typedef std::map<std::string, void *(D::*)()> UrlRuleMap;

    static UrlRuleMap & urlRules () {
        static UrlRuleMap urlRules_;
        return urlRules_;
    }

    void * invokeRule (const std::string &s) {
        typename UrlRuleMap::iterator i = urlRules().find(s);
        if (i == urlRules().end()) return 0;
        return (dynamic_cast<D *>(this)->*(i->second))();
    }

protected:
    static void regController (void *(D::*m)(), const std::string &s) {
        urlRules()[s] = m;
    }
};
#define REG_RULE(D, x) BS_Proxy<D>::regController(&D::x, #x)

class DerivedController : public BS_Proxy<DerivedController> {
    struct Populate {
        Populate () {
            REG_RULE(DerivedController, print);
            REG_RULE(DerivedController, printView);
        }
    };
public:
    DerivedController() {
        static Populate populate_;
    }
    void * print() { return NULL; }
    void * printView() {
        std::cout<<"Print view!"<<std::endl;
        return NULL;
    }
};
// DerivedController rules
DERIVED_RULE_INC(print)
DERIVED_RULE_INC(printView)
//...
class DerivedController : public BS_Proxy<DerivedController> {
    struct Populate {
        Populate () {
            #define DERIVED_RULE_INC(x) REG_RULE(DerivedController, x);
            #include "derived_controller_rules.inc"
            #undef DERIVED_RULE_INC
        }
    };
public:
    DerivedController() {
        static Populate populate_;
    }
    #define DERIVED_RULE_INC(x) void * x ();
    #include "derived_controller_rules.inc"
    #undef DERIVED_RULE_INC
};

void * DerivedController::print() { return NULL; }

void * DerivedController::printView() {
    std::cout<<"Print view!"<<std::endl;
    return NULL;
}