在基本模板函数中访问派生类的成员函数 [英] Accessing derived class' member functions in base template function

查看:79
本文介绍了在基本模板函数中访问派生类的成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为DBDriver的类,该类处理与数据库中给定表的通信.它的公共入口点是称为execute_query()的功能模板,该模板执行SELECT查询.调用此函数后,将执行一些数据库逻辑,然后使用结果填充提供的(模板类型的)容器.看起来类似于以下内容:

I have a class called DBDriver that handles communication with a given table in a database. Its public entry point is a function template called execute_query(), which executes SELECT queries. Upon calling this function, some database logic is performed, and then a provided container (of the template type) is populated with results. This looks something like the following:

class DBDriver {

    ...

    template <typename CONT_T>
    void execute_query(const std::string& query, CONT_T& container);

    ...

};

template <typename CONT_T>
void DBDriver::execute_query(const std::string& query, CONT_T& container) {
    DBCursor& cursor = ...  // some database logic here
    populate_container(container, cursor);
}

当然,上面的内容不会编译,因为populate_container()DBDriver中未定义.

Of course, the above will not compile, as populate_container() is not defined in DBDriver.

DBDriver应该是纯虚拟的,并具有多个派生类(所涉及的每个数据库表都有一个类).每个派生类都将定义其自己的populate_container()重载,每种相关容器类型都应重载一个.这将类似于以下内容:

DBDriver should be purely virtual and have several classes derive from it (one for each database table involved). Each derived class will define its own overloads of populate_container(), one for each relevant container type. This will look something like the following:

class SampleTableDBDriver : public DBDriver {

    // ...

    populate_container(const ContainerTypeOne& container, DBCursor& cursor);
    populate_container(const ContainerTypeTwo& container, DBCursor& cursor);

    // ...

};

我最初的尝试没有成功,因为我需要在DBDriver中定义一个虚拟函数模板作为派生类的populate_container()重载的入口. (当然,这种事情在C ++中是不存在的,因此是我的问题.)

My original attempt at this was unsuccessful, as I would have needed to define a virtual function template in DBDriver to serve as an entry point to a derived class' populate_container() overloads. (Of course such a thing does not exist in C++, hence my issue.)

是否存在针对此类问题的更简洁,惯用的解决方案?

Is there a cleaner, idiomatic solution for this type of problem?

推荐答案

execute_query是模板函数的原因是您需要通用容器.如果为容器定义Interface怎么办?

The reason why execute_query is a template function is you need a generic container. What if you define a Interface for the container?

class IContainer
{};

模板功能不能是虚拟的.因此,您可以使用模板方法设计模式.

Template Functions cannot be virtual. Therefore, you can use the Template Method Design Pattern.

class DBDriver 
{
    public:
    void execute_query(const std::string& query, IContainer **_ppContainer);
    {
        DBCursor& cursor = ...  // some database logic here
        populate_container(_ppContainer, cursor);
    }

    virtual void populate_container(IContainer **_ppContainer, DBCursor &_dbCursor) = 0;
};

并让每个派生类实现populate_container并提供其自定义Container.

And let every derived class implement populate_container and also provide their custom Container.

class SampleTableDBDriver : public DBDriver 
{
    public:
        class ContainerTypeOne : public IContainer
        {};

        void populate_container(IContainer **_ppContainer, DBCursor &_dbCursor) 
        {
              ContainerTypeOne *pContainer = new ContainerTypeOne();
              //....
              (*_ppContainer) = pContainer;
        }
};


SampleTableDBDriver  oSampleDriver;
IContainer *pContainer = NULL;
std::string szQuery = // some query ;
oSampleDriver.execute_query(szQuery, &pContainer);
if(pContainer != NULL)
{
    SampleTableDBDriver::ContainerTypeOne  *pSampleDriverContainer = 
        dynamic_cast<SampleTableDBDriver::ContainerTypeOne*>(pContainer); 

    //use pSampleDriverContainer 
}

编辑:用于支持多个容器.

For supporting multiple containers.

在您的原始设计中,populate_container似乎在派生类中被重载.在这种情况下,您仍然可以在调用execute_query时从外部传递 exact 容器. 此Template Method设计可以完成相同的操作.然后,您将需要在populate_container函数中解密容器的类型,如下所示:

In your original design the populate_container seems to be overloaded in derived classes. In that case you would still pass the exact container from outside while calling execute_query. Same thing can be done with this Template Method design. Then, you will need to decipher the type of container inside the populate_container function as follows:

新签名:int populate_container(IContainer *_pContainer, DBCursor &_dbCursor)

int populate_container(IContainer *_pContainer, DBCursor &_dbCursor) 
{
      if(dynamic_cast<ContainerTypeOne *>(_pContainer) != NULL)
      {
          ContainerTypeOne *pContainerOne = _pContainer;
          //populate the result by using pContainerOne
          return 1;   
      }

      if(dynamic_cast<ContainerTypeTwo *>(_pContainer) != NULL)
      {
          ContainerTypeOne *pContainerTwo = _pContainer;
          //populate the result by using pContainerTwo
          return 1;   
      }

      //no, I do not support the container you passed.
      return 0;
}

SampleTableDBDriver  oSampleDriver;
SampleTableDBDriver::ContainerTypeOne oSampleContainerTypeOne;
std::string szQuery = // some query ;
if(oSampleDriver.execute_query(szQuery, &oSampleContainerTypeOne) != 0)
{
    //use oSampleContainerTypeOne;
}

这篇关于在基本模板函数中访问派生类的成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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