在函数中是否可以将类型作为参数?
我想为一个数据库类写一个函数,它基本上只是一个包围对象(比如形状)的hash_map的包装,它由ID号索引,它将查找一个ID并将其转换为适当的指针类型。在函数中是否可以将类型作为参数?
例如我希望能够做到这样的事情:
Circle* shapeToLookup = NULL;
int idNum = 12;
database.lookup(idNum, circleToLookup);
if(circleToLookup != NULL)
{
// Do stuff with the circle.
}
并让数据库知道它的参数的类型。有没有办法做到这一点,而不是超载功能(lookup(int, Circle*)
,lookup(int, Rect*)
,广告nauseum)?你能否声明一个像lookup(int, Shape*)
这样的函数,并且知道它给出了哪种类型?
谢谢!
您可以使用模板来做到这一点。
编辑:基于额外信息的新实现。如果mymap
是std::map<int, Shape*>
:
template <typename T>
void lookup(int idNum, T* &ptr) {
auto it = mymap.find(idNum);
if (it == mymap.end()) {
ptr = 0;
} else {
ptr = dynamic_cast<T*>(*it); // Shape must have a virtual member function
}
}
或者你可能更喜欢:
template <typename T>
T* lookup(int idNum) {
auto it = mymap.find(idNum);
if (it == mymap.end()) {
return 0;
}
return dynamic_cast<T*>(*it);
}
然后调用它像Circle *circle = database.lookup<Circle>(123);
显然多态性容器的乐趣本身就是一个一大堆,但我会假设你已经排序。那里可能有一个shared_ptr
,我已经遗漏了。
旧的实现时,我想到了DB可以存储POD的副本:
template <typename T>
void lookup(int idNum, T* &ptr) {
void *theresult = // something based on idNum
// some check needed here that theresult really is the right type.
// how you do this depends on the database, but suppose that
// the database gives us some integer "type" which indicates the type
if (type != type_constant<T>::value) {
ptr = 0;
} else {
ptr = static_cast<T*>(theresult);
}
}
type_constant是 “型特征” 的一个例子,你实现它想:
template <typename T>
struct type_constant {};
template <>
struct type_constant<Circle> {
static const int value = 1;
};
template <>
struct type_constant<Rectangle> {
static const int value = 2;
};
// etc...
我们是否应该不使用dynamic_cast 投向儿童类型。 (即从Shape *到Circle *)? – 2010-08-19 15:55:45
也许吧。我不知道这个数据库实际上是否返回 - 如果它是一个'Shape *',它的referand是一个子类,并且'Shape *'具有任何虚拟成员函数,那么是的。如果数据库本身不是基于对象的,或者某个地方的某个人必须根据指示类型的记录来执行某些操作。我无法从“Shape *”是一个实际的基类的问题或者问题提及者认为它可能是解决方案的一部分的问题中断言。 – 2010-08-19 15:59:10
我不知道'type_constant',我可能会像马丁所说的那样看着'dynamic_cast'。一个facepalm的位,不用马上思考模板。 – spbots 2010-08-19 16:01:32
其他人已经解释了如何将一个类型传递给一个函数(通过使用函数模板)。我想给另一种观点:
这可能是更好的对Shape
引入一个新的虚函数,然后Do stuff with the Circle
部分移动到在Cricle
类,虚函数的重新实现。
这样,您就不需要知道类型。您只需从数据库中获取Shape
对象,然后调用doStuff()
函数 - 并且它根据Shape
的实际类型执行正确的操作。虚拟函数的一个很好的用例。 :-)
当然,这可能或多或少简单一些,具体取决于Do stuff
的实际情况。
不幸的是,这是遗留代码中的一个重要的重构工作,其中“形状”都严重依赖于其他形状,因此查找实际上是在其他形状内部发生的,doStuff()不一定是通用功能。感谢虽然:) – spbots 2010-08-19 15:55:56
template <T>
Database::lookup(int idNum, T TobjectToLookup)
{
// inside here, T is the type of the object passed in/
}
IMO,这实际上是一个数据库问题。你也不会说什么数据库。我会查看SQL关键字“LIKE”。 – JustBoo 2010-08-19 15:49:36
你打算如何将类型信息传递给数据库? (或者我应该说,数据库将如何接收它?) – 2010-08-19 15:50:19
如果您希望数据库使用此信息*执行某些操作*,则必须编写一些特定于圆的代码,某些矩形特定的代码等等令人厌恶。问题是*你想把这个代码放在哪里。你能告诉我们你想要数据库做什么吗? – Beta 2010-08-19 15:51:50