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;
}