C ++多态 - 自动检测派生类型

时间:2010-08-06 04:31:13

标签: c++ oop polymorphism

我有一些我想要优化的代码。它看起来像这样:

function abc( string format ) {
  if (format == "a") { // this is a string, I shouldn't have used single quote, sorry for the confusion
    classx::a t;
    doit(t);
  }
  if (format == "b"){
    classx::b t;
    doit(t);
  }
  if (format == "c"){
    classx::c t;
    doit(t) 
  }
  if (format == "d"){
    classx::d t; 
    doit(t);
  }
}

目前有许多不同类型的doit()函数

function doit( classx:a ) {
   different code for a
}

function doit( classx:b ) {
   different code for b
}

...等

如您所见,复制了大量代码。但是我无法弄清楚如何减少这些词。 注意 : doit(x)因不同类型而过载。 a,b,c,d类派生自名为“X”的类。

我可以创建一个指针类型classx :: X:

classx::X *t;
if (format == "a") t = new classx::a
if (format == "b") t = new classx::b
if (format == "c") t = new classx::c
if (format == "d") t = new classx::d
doit(*t)

但是仍然需要为类型classx :: X写一个doit(),带有一堆“if then”并转换为正确的类型......因为C ++无法自动检测并转换为正确的类型。

我想知道是否有更快/更聪明的方法来做到这一点。 提前谢谢。

6 个答案:

答案 0 :(得分:3)

减少重复添加到功能映射的新条目的一种可能方法:

template<class T> void innerAbc() {
    T t;
    doit(t);
}

typedef std::map<std::string, void (*)()> FuncMap;

FuncMap initHandlers() {
    FuncMap m;
    m["a"] = &innerAbc<classx::a>;
    // ... extend here
    return m;
}   

void abc(const std::string& format) {
    static const FuncMap handlers = initHandlers();
    FuncMap::const_iterator it = handlers.find(format);
    if (it != handlers.end()) 
        it->second();
}

答案 1 :(得分:1)

将格式/构造函数对放入字典中。关键是格式字符串,该值是一个指向静态工厂方法的函数指针,该方法本质上只是构造函数的一个瘦包装器。除了更容易维护之外,它还会进行哈希查找或二进制搜索,具体取决于您使用的字典/地图的类型。

答案 2 :(得分:1)

如果您在第一个else if之后使用if会更快,以便在找到匹配后不会继续测试。这样更紧凑,更易于阅读...

function abc(string format) {
    if (format == 'a')
        doit(classx::a());
    else if (format == 'b')
        doit(classx::b());
    else if (format == 'c')
        doit(classx::c())
    else if (format == 'd')
        doit(classx::d());
}

答案 3 :(得分:1)

一个简单的模板方法摆脱了大量重复的代码。如果你想避免使用一系列'if'语句,你可以使用map或带二进制搜索的有序向量。

template<typename T> void forward_doit()
{
    T t;
    doit(t);
}

void func(string const& s)
{
    if (s == "a") return forward_doit<Classx::a>();
    if (s == "b") return forward_doit<Classx::b>();
    if (s == "c") return forward_doit<Classx::c>();
    // ...
}

答案 4 :(得分:0)

这是一种使用宏的方法,假设格式实际上是一个字符串。您在原始(Javascript?)代码中使用的单引号是用于字符。

我无法使用模板进行远程操作,是的,有时宏仍然有用!

#define FORMATTER(ltr) \
    if (format == #ltr) { \
    classx::##ltr t; \
    doit(t); \
  }

#define ELSEFORMATTER(ltr) else FORMATTER(ltr)

void abc( std::string format ) {
    FORMATTER(a)
    ELSEFORMATTER(b)
    ELSEFORMATTER(c)
    ELSEFORMATTER(d)
}

答案 5 :(得分:0)

使用boost预处理器

#define MACRO(r, data, elem)                     \
if (format == '(elem)')  doit(classx::(elem)()); \
else

BOOST_PP_SEQ_FOR_EACH(MACRO, _, (a)(b)...) {
... // else condition
}

我不知道如何将宏放在''内:How to single-quote an argument in a macro?