问题描述
我有一个名为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;
}
这篇关于在基本模板函数中访问派生类的成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!