使用gcc编译模板类时,容易遇到编译错误。形如:找不到变量等。为此问题,在网上搜索了一番。
模板类的变量解析分为两个步骤:
1. 模板类解析过程
这个过程中,需要解析与泛型参数无关的变量名、函数名。如下代码,
typedef void (*cb)();
template <typename fieldType>
class TestClass{
public:
fieldType m_functionPtr;
int m_i;
TestClass(fieldType ptr):m_functionPtr(ptr){m_i = 0;}
virtual void invoke()
{
}
};
template <typename fieldType>
class DerivedClass : public TestClass<fieldType>{
public:
DerivedClass(fieldType ptr):TestClass<fieldType>(ptr){};
virtual void invoke()
{
//if (TestClass<fieldType>::m_functionPtr != 0)
//{
// TestClass<fieldType>::m_functionPtr();
//}
if (m_functionPtr != 0)
{
m_functionPtr();
}
std::cout << m_i;
}
};
方法DerivedClass<fieldType>::invoke直接使用了m_i, m_functionPtr。在解析模板类DerivedClass过程中,这些变量名会被作为与泛型参数无关的变量名称。这个过程中,并没有TestClass类,也没有DerivedClass类,这两个类只是模板。因此,只能在全局作用域查找这些变量名称的声明。结果是找不到,也就出现了编译错误。
2. 模板类实例化过程
在这个过程中,会解析与泛型参数有关的变量名、函数名。如下代码,
template <typename fieldType>
class TestClass{
public:
fieldType m_functionPtr;
int m_i;
TestClass(fieldType ptr):m_functionPtr(ptr){m_i = 0;}
virtual void invoke()
{
}
};
template <typename fieldType>
class DerivedClass : public TestClass<fieldType>{
public:
DerivedClass(fieldType ptr):TestClass<fieldType>(ptr){};
virtual void invoke()
{
if (TestClass<fieldType>::m_functionPtr != 0)
{
TestClass<fieldType>::m_functionPtr();
}
//if (m_functionPtr != 0)
//{
// m_functionPtr();
//}
std::cout << this->m_i;
}
};
m_functionPtr与模板实例化类TestClass<fieldType>有关,也就与泛型参数fieldType有关。m_i与this有关,也就与模板实例化类DerivedClass<fieldType>有关,也就与fieldType有关。因此,这两个名称的解析就会被延迟到模板实例化过程中。在实例化过程中,父类TestClass<fieldType>已经被创建了。因此,可以在父类中找到这两个变量名,也就不会出现编译错误了。
参考:http://www.cppblog.com/fwxjj/archive/2012/03/04/167096.aspx