【问题标题】:How to implement a polymorphic function within member function in C++11?如何在 C++11 的成员函数中实现多态函数?
【发布时间】:2015-05-06 04:25:21
【问题描述】:

我正在使用其他人编写的框架。该框架使用了一些丑陋的宏。 首先,框架使用宏来声明和定义类,如下所示:

#define DECLARE_FUNC(_name, _params) \
class _name                          \
{                                    \
    static int execute();            \
    static int exec_func(_params* param);          \
}

#define DEFINE_FUNC(_name, _params)  \
int _name::execute()                 \
{                                    \
    _params p = get_from_global();   \
    return exec_func(&p)             \
}                                    \
int _name::exec_func(_param* param)

在使用这个框架时,我要做的是:

DECLARE_FUNC(foo, database)

DEFINE_FUNC(foo, database)
{
    // write business logic here        
}

在编写业务逻辑时,我必须从数据库中的不同表中查询信息,并对查询结果做几乎相同的事情。伪代码如下:

TypeA a = TABLE(t_TypeA)->Query();
if (a.is_valid()) {
   // do something with a here
   // some local variables are used here
}

TypeB b = TABLE(t_TypeB)->Query();
if (b.is_valid()) {
   // do something with b here
   // some local variables are used here
}

显然重复代码太多了,不好。所以我的同事使用宏来删除重复的代码。我认为多态 lambda 在这种情况下应该可以工作,但是 C++11 不支持多态 lambda。

我的问题:有没有其他方法可以删除没有宏的重复代码?

更新: 其实源代码中“_params”也是一个宏,可以扩展更多参数,我这里简化一下。如果扩展参数宏并使用多态 lambda,它看起来像:

int ClassA::exec_func(Database database,
                      Date date,
                      Time time)
{
    // there are also some local variables, for example:
    long second = get_second(date, time);

    // polymorphic lambda version
    auto handle_table = [&](auto table_type) {
        // database, date, time and local variables will be used here
    }

    handle_table(TableA);
    handle_table(TableB);
    ...
    handle_table(TableX);
}

所以弗朗西斯的解决方案在这种情况下可能行不通。

【问题讨论】:

  • 接受函数指针和数据库类型作为其模板参数的抽象模板基类会起作用吗?这样你的基类是抽象的,不能被实例化,但派生类可以是它们都共享一个相似接口的地方。每个派生类(数据库类型)独有的任何函数或方法都可以通过使用模板特化覆盖纯虚函数来完成。
  • 老实说,我不确定您的问题是什么,您能否写一个草图如何使用多态 lambda 解决您的问题?另外,您希望避免哪些重复代码?最后,我会认真地问自己是否有充分的理由使用该框架,因为您展示的部分提出了一些非常复杂的设计,这些设计只能在预可变模板(甚至预模板)中得到证明时代。
  • @Ulrich 对我来说,这确实看起来像是一个可以选择模板的场景。但如果可能的话,弗朗西斯的解决方案会更好。一般来说,如果我有对类的部分数据执行相同操作的函数,我会尝试使用继承来解决它。
  • std::function 不够吗?
  • 感谢您的建议。稍后我将添加更多代码以使其更清晰。 @Ulrich 我完全同意你的观点,框架很糟糕,设计更糟糕。是的,没有很好的理由使用它,但这是公司的选择,我必须忍受它。

标签: c++ c++11 lambda macros


【解决方案1】:

lambdas 可以用类函子编写。

auto l = [&capture](auto param) {/*code*/};

变成这样:

class MyFunctor
{
public:
    explicit MyFunctor(const capture_t& capture) : capture(capture) {}

    template <typename T>
    void operator () (T param) const { /* code */ }
private:
    const capture_t& capture; // or by value
};

以后

 auto l = MyFunctor(capture);

【讨论】:

  • 谢谢。但是 capture_t 是什么?你能给我一些参考吗?
  • capture_t 是变量capture 的类型。
  • 如何在您的实现中捕获多个参数?因为我也想使用私有数据成员。函子将不得不捕获太多参数
  • @Neal:使用多个成员并向构造函数添加额外的参数。
猜你喜欢
  • 2021-06-02
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
相关资源
最近更新 更多