如何在C ++中使用动态方法 [英] How can I use Dynamic Methods in C++

查看:168
本文介绍了如何在C ++中使用动态方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现自己在C ++中写了一些重复的代码。我使用一些自动生成,如果我想处理Foo,Bar,& Baz他们都有相当类似的方法。例如,get_foo,get_bar,get_baz等。

I've found myself writing some repetitious code in C++. I'm using some auto-generated, such that if I want to deal with Foo, Bar, & Baz they all have fairly similar method. E.g., get_foo, get_bar, get_baz, etc.

对于每个事物,我或多或少都必须做相同类型的事情。检查是否存在,如果存在,获取日志,查找日志中的最近条目,检查条目的问题等。

For each "thing" I more or less have to do the same types of thing. Check if it exists, if it does, get the log, look for the most recent entry in the log, check the entry for problems, etc.

重复代码的公正位,沿着以下行:

That's lead to a fair bit of repeated code, along the lines of:

if (obj->has_foo) {
  if(obj->get_foo().has_log()) {
    Log *l = obj->get_foo().get_foo_log();
    if (!l) {
      ERROR("Foo does not have a log")
    }    
    ... 30-40 more lines of stuff ...
  }
}

if (obj->has_bar) {
  if(obj->get_bar().has_log()) {
    Log *l = obj->get_bar().get_bar_log();
    if (!l) {
      ERROR("Bar does not have a log")
    }    
    ... 30-40 more lines of stuff ...
  }
}

if (obj->has_baz) {
  if(obj->get_baz().has_log()) {
    Log *l = obj->get_baz().get_baz_log();
    if (!l) {
      ERROR("Baz does not have a log")
    }    
    ... 30-40 more lines of stuff ...
  }
}

有没有办法我可以建立一个集合,在集合中将具有Foo,Bar,Baz和我可以在单个代码块中使用它们的独特方面。

Is there a way I could build a collection, such that each item in the collection would have the unique aspects of Foo, Bar, Baz and I could use them in a single block of code.

原谅Perl-eese, :

Forgive the Perl-eese, but something like:

foreach my $thingie ("foo", "bar", "baz") {
    if (obj->has_$thingie) {
      if(obj->get_$thingie().has_log()) {
        Log *l = obj->get_$thingie().get_$thingie_log();
        if (!l) {
          ERROR(sprintf("%s does not have a log", $thingie))
        }    
        ... 30-40 more lines of stuff ...
      }
    } 
}

如果这不是正确的方向,我如何避免复制/粘贴/调整相同的基本块3次?

Or, if that's not the right direction, how do I avoid copy/pasting/tweaking that same fundamental block 3 times?

推荐答案

代码未经测试,我可能错过了成员指针和类型推导的一些问题,或者我可能只是留下了错误):

Sure (code untested, I might have missed some problem with member pointers and type deduction, or I might just have left bugs):

template <typename T, typename M, typename F, typename G>
void doChecks(T *obj, M has_member, F get_fn, G getlog_fn) {
    if (obj->*has_member) {
        if (obj->*get_fn().has_log()) {
            Log *l = obj->*get_fn().*getlog_fn();
            if (!l) {
                ERROR("%s does not have a log", typeid(T).name());
            }
        }
     }
}

MyObj obj;
doChecks(obj, &MyObj::has_foo, &MyObj::get_foo, &Foo::get_foo_log);
doChecks(obj, &MyObj::has_bar, &MyObj::get_bar, &Bar::get_bar_log);
doChecks(obj, &MyObj::has_baz, &MyObj::get_baz, &Baz::get_baz_log);

显然你可以使用functor类型的模板参数,但这是最接近perl的方法,实际上建立一个字典到对象和滚动自己的调度。你也可以宏观调用doChecks的调用,如果你愿意,并使用一些令牌粘贴,使它们有点缩短:

Obviously you could use a functor-type template parameter, but this is the closest to the perl approach without actually building a dictionary into the object and rolling your own dispatch. You could also macro-ise those calls to doChecks if you wanted, and use some token-pasting to make them a bit shorter:

#define DOCHECKS(obj, class, thing) doChecks(obj, &MyObj::has_##thing, &MyObj::get_##thing, & class :: get_##thing##log) 

DOCHECKS(obj, Foo, foo);
DOCHECKS(obj, Bar, bar);
DOCHECKS(obj, Baz, baz);

使用额外的预处理器魔法,你可能会使它成为一个循环,查看Boost预处理器库或混沌预处理器。

With additional preprocessor wizardry you can probably make it a loop, not sure. Look at the Boost preprocessor library or the Chaos Preprocessor.

这篇关于如何在C ++中使用动态方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆