代码之家  ›  专栏  ›  技术社区  ›  w00d

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

  •  5
  • w00d  · 技术社区  · 14 年前

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

    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 回复  |  直到 14 年前
        1
  •  3
  •   Georg Fritzsche    14 年前

    一种可能的方法可以减少向函数映射添加新条目的重复:

    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();
    }
    
        2
  •  1
  •   Steven Sudit    14 年前

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

        3
  •  1
  •   Nick Strupat    14 年前

    如果你用的话会更快 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());
    }
    
        4
  •  1
  •   janm    14 年前

    一个简单的模板方法可以消除很多重复的代码。如果你想避免有一系列的“if”语句,你可以使用一个映射,或者一个带二进制搜索的排序向量。

    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>();
        // ...
    }
    
        5
  •  0
  •   Andy Dent    14 年前

    下面是一种使用宏的方法,它假定格式实际上是一个字符串。原始(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)
    }
    
        6
  •  0
  •   Community CDub    8 年前

    使用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?