【发布时间】:2024-01-13 19:15:01
【问题描述】:
这是一个奇怪的问题,因为我已经知道“编码”的答案。我只是想更好地理解为什么会这样。这里有一些大师比 C++ 标准更擅长解释这些事情:)
下面我们有一种方法可以定义一个抽象工厂模板,它根据字符串作为键来分配对象(这是一个人为的例子):-
#include <iostream>
#include <map>
#include <string>
using namespace std;
template <typename T, typename TProduct>
TProduct *MyFactoryConstructHelper(const T *t)
{
if (!t) return new T;
return new T(*static_cast<const T*>(t));
}
template <typename TProduct>
class AbstractFactory
{
public:
typedef TProduct *(*MyFactoryConstructor)(const void *);
typedef map<string, MyFactoryConstructor> MyFactoryConstructorMap;
static TProduct *Create(const string &iName)
{
MyFactoryConstructor ctr = mTypes[iName];
TProduct *result = NULL;
if(ctr) result = ctr(NULL);
return result;
}
template <typename T>
static bool Register(const string &iName) {
typedef TProduct*(*ConstructPtr)(const T*);
ConstructPtr cPtr = MyFactoryConstructHelper<T, TProduct>;
string name = iName;
mTypes.insert(pair<string,MyFactoryConstructor>(name, reinterpret_cast<MyFactoryConstructor>(cPtr)));
return(true);
}
protected:
AbstractFactory() {}
static MyFactoryConstructorMap mTypes;
};
template <typename TProduct>
map<string, /*typename*/ AbstractFactory<TProduct>::MyFactoryConstructor> AbstractFactory<TProduct>::mTypes;
以下是我们如何使用它的示例:-
class MyProduct
{
public:
virtual ~MyProduct() {}
virtual void Iam() = 0;
};
class MyProductFactory : public AbstractFactory<MyProduct>
{
public:
};
class ProductA : public MyProduct
{
public:
void Iam() { cout << "ProductA" << endl; }
};
class ProductB : public MyProduct
{
public:
void Iam() { cout << "ProductB" << endl; }
};
int _tmain(int argc, _TCHAR* argv[])
{
MyProduct *prd;
MyProductFactory::Register<ProductA>("A");
MyProductFactory::Register<ProductB>("B");
prd = MyProductFactory::Create("A");
prd->Iam();
delete prd;
prd = MyProductFactory::Create("B");
prd->Iam();
delete prd;
return 0;
}
它不会按原样编译,抱怨地图没有数据类型的有效模板类型参数。但是如果你在静态成员定义中删除'typename'关键字周围的cmets,一切都会编译并且工作正常......为什么?
还有,我能把它做得更好吗? :)
【问题讨论】:
-
你应该至少指向你所指的那一行?
-
在 Stack Overflow C++ FAQ 条目“Where to put the "template" and "typename" on dependent names”中有一个很好的解释为什么需要
typename
标签: c++ templates map factory typename