Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何调用C++;通过函数指针具有不同签名的函数 我有一个C++应用程序,其中,主程序()实例化对象MyApp,然后将对象传递到Read CONFIG函数。< /P>_C++_Functor - Fatal编程技术网

如何调用C++;通过函数指针具有不同签名的函数 我有一个C++应用程序,其中,主程序()实例化对象MyApp,然后将对象传递到Read CONFIG函数。< /P>

如何调用C++;通过函数指针具有不同签名的函数 我有一个C++应用程序,其中,主程序()实例化对象MyApp,然后将对象传递到Read CONFIG函数。< /P>,c++,functor,C++,Functor,ReadConfig打开一个基于文本的文件,对其进行解析,并调用相应的MyApp方法对其进行配置 class MyApp { private: public: void SetRate(uint16_t); void EnableLogging(bool); void SetAddress(uint32_t); }; 我正试图使ReadConfig的维护变得容易,这样当新的公共方法被添加到MyApp中时,它就可以像更新表一样简单。我提出了以下解决方案,但我不喜欢。由于必须确保将0

ReadConfig打开一个基于文本的文件,对其进行解析,并调用相应的MyApp方法对其进行配置

class MyApp
{
private:

public:
  void SetRate(uint16_t);
  void EnableLogging(bool);
  void SetAddress(uint32_t);
};
我正试图使ReadConfig的维护变得容易,这样当新的公共方法被添加到MyApp中时,它就可以像更新表一样简单。我提出了以下解决方案,但我不喜欢。由于必须确保将0放置在正确的位置,因此很难进行维护

下面是一个我能够解决的问题的例子。任何建议,使这更好将不胜感激。注意我在嵌入式工作,所以我们使用的C++编译器不支持C++ 14,没有升压。我希望避免使用任何STL库,以便自己理解这样做的机制

以下是我所拥有的:

enum ARGTYPE {TBOOL, TUINT16, TUINT32};

template<typename TOBJ, typename TARG>
struct TSetting
{
  void (TOBJ::*FSet)(TARG);
};

template<typename obj>
struct SETTINGFN
{
  const char                       *setting_name;
  ARGTYPE                          Targ;
  TSetting<obj,bool>               HBool;
  TSetting<obj,uint16_t>           HUint16;
  TSetting<obj,uint32_t>           HUint32;
};

SETTINGFN<MyApp> MyAppSettings[] =
{
  "logging"    ,TBOOL,       &MyApp::EnableLogging, 0,0,0
  ,"maxrate"   ,TUINT16,     0,0,0,&MyApp::SetRate
  ,"address"   ,TUINT32,     0, &MyApp::SetAddress, 0,0

};
unsigned int MyAppSettings_Count = sizeof(MyAppSettings) / sizeof(SETTINGFN<MyApp>);
enum ARGTYPE{TBOOL,TUINT16,TUINT32};
模板
结构设置
{
无效(TOBJ::*FSet)(TARG);
};
模板
结构设置fn
{
常量字符*设置名称;
arg型Targ;
TSetting HBool;
TSetting HUint16;
TSetting HUint32;
};
设置fn MyAppSettings[]=
{
“日志记录”、TBOOL和MyApp::EnableLogging,0,0,0
、maxrate、TUINT16、0,0,0和MyApp::SetRate
,“地址”,TUINT32,0和MyApp::SetAddress,0,0
};
unsigned int MyAppSettings\u Count=sizeof(MyAppSettings)/sizeof(SETTINGFN);
然后,当我读取配置文件并解析它时,我调用一个函数来处理通过函数指针调用实际的MyApp函数。该职能如下:

bool AppSetting(MyApp &E, TObjnode &node)
{
  bool rval = false;

  for(unsigned int i=0; i<MyAppSettings_Count && !rval; i++)
  {
    if(node.GetName() == MyAppSettings[i].setting_name)
    {
      rval = true;

      switch(MyAppSettings[i].Targ)
      {
        case TBOOL:
          (E.*MyAppSettings[i].HBool.FSet)(node.GetValue().AsBool());
        break;

        case TUINT16:
          (E.*MyAppSettings[i].HUint16.FSet)(node.GetValue().Value());
        break;

        case TUINT32:
          (E.*MyAppSettings[i].HUint32.FSet)(node.GetValue().Value());
        break;
      }
    }
  }

  return(rval);
}
bool应用设置(MyApp&E、TObjnode&node)
{
bool-rval=false;

对于(unsigned int i=0;i而言,设计中的难点在于不同的参数类型

如果将参数抽象为一个结构,那么函数可以简化为一个固定的签名

通过使用基本结构,签名和签名将更加通用:

struct Arguments_Base
{
};

void SetRate(Arguments_Base& ab);
void EnableLogging(Arguments_Base& ab);
void SetAddress(Arguments_Base& ab);
通过具有统一的签名,可以在表或映射中使用函数指针或函数对象,从而使搜索更容易。搜索引擎应该能够是通用的,并且取决于数据的大小,以便只需要更改数据(例如表),而不需要更改搜索引擎

每种类型的参数集都应从
arguments\u Base
类派生。然后,函数可以
dynamic\u cast
基类引用


另请参见:工厂设计模式、访客设计模式、双重分派

设计中的难点是不同的参数类型

如果将参数抽象为一个结构,那么函数可以简化为一个固定的签名

通过使用基本结构,签名和签名将更加通用:

struct Arguments_Base
{
};

void SetRate(Arguments_Base& ab);
void EnableLogging(Arguments_Base& ab);
void SetAddress(Arguments_Base& ab);
通过具有统一的签名,可以在表或映射中使用函数指针或函数对象,从而使搜索更容易。搜索引擎应该能够是通用的,并且取决于数据的大小,以便只需要更改数据(例如表),而不需要更改搜索引擎

每种类型的参数集都应从
arguments\u Base
类派生。然后,函数可以
dynamic\u cast
基类引用


另请参阅:Factory设计模式、Visitor设计模式、Double Dispatch

考虑将字符串传递给每个setter,并让它们调用特定于类型的可重用解析代码?这样所有setter都可以是同一类型。接受字符串并同时调用解析函数和类型安全setter的蹦床可能更好。因此。。。为了避免每次添加新属性/设置程序时都必须向配置分派例程添加函数调用,您希望每次添加新属性/设置程序时都更新专有数据结构?我想每个属性/设置程序都有自己的属性/设置程序…我想到了这些,但我希望避免更改当前函数签名或添加新的函数签名您使用如此复杂的方案只是为了应用程序配置,这有什么原因吗?哦,bump,5分钟后无法编辑注释。无论如何,我想补充的是:无论如何,我曾经尝试并坚持的是非常简单但超级有效的方法,类似于本文所述的方法:考虑将字符串传递给每个setter,然后g他们调用特定于类型的可重用解析代码?那么所有setter都可以是同一类型。一个接受字符串并同时调用解析函数和类型安全setter的蹦床可能更好。因此…为了避免每次添加新属性/setter时都必须向配置分派例程添加函数调用,您希望每次添加新属性/设置程序时更新专有数据结构?每个属性/设置程序都有自己的属性/设置程序,我想…我想到了这些,但我希望避免更改当前函数签名或添加新的属性/设置程序。这是您仅为应用程序配置而使用如此复杂方案的原因吗?哦,bump,5分钟后无法编辑注释tes.无论如何,我想补充的是:无论如何,我曾经尝试并坚持的是一种非常简单但超级有效的方法,类似于本文中描述的方法:信不信由你,我想到了这一点,但我希望避免更改当前的函数签名或添加新的签名-但这很优雅。@rubenvb不需要动态转换如果基类提供了一个派生类可以重载的方法。想想NVI设计模式。或者,基类可以简单地进行转换,如果像Ben Voigt建议的那样,参数\u base是一个可以返回值(int、bools等)的字符串类@Eric yes,听起来更像:).信不信由你,我想到了这一点,但我希望避免更改当前的函数签名或添加新的签名-但这很优雅。@rubenvb如果