一般来说犯错误的都是开发者.VS的错误还是蛮少的.额..除了预编译头有时候会错误要Clean一下.
今天确实遇到了一个bug.查了半天.又写了好些测试代码.才把错误模型整理出来.
发现是在存在虚函数表时对于父类模板类的偏移计算错误.这句话说的挺绕口.
据说也和VS对代码限制较少有关.在GCC下是编译不过去的.
模型挺简单
template< class T > class TestTClass { public: T i; std::vector<T> m_vec; T GetNumber() { return i; } int GetSize() { return m_vec.size(); } }; class TestClass : public TestTClass<int> { public: TestClass() { i = 1; } int GetNumber() { return TestTClass::GetNumber(); } int GetSize() { return TestTClass::GetSize(); } };
TestClass kClass; kClass.i = 3; kClass.m_vec.push_back( 1 ); int iTest = kClass.GetNumber(); int iSize = kClass.GetSize();
但如果将GetSize改成虚函数.
class TestClass : public TestTClass<int> { public: TestClass() { i = 1; } int GetNumber() { return TestTClass::GetNumber(); } virtual int GetSize() { return TestTClass::GetSize(); } };
TestClass kClass; kClass.i = 3; kClass.m_vec.push_back( 1 ); int iTest = kClass.GetNumber(); int iSize = kClass.GetSize();
如果是虚继承的话 like this:
class TestClass : virtual public TestTClass<int>又没有问题.
根据现象分析.虚继承时父类包含有指向子类的指针.地址已经固定了.所以正确.由此推断可能是由于根据虚函数表计算子类地址时有错误.
但有一点必须指出.
return TestTClass::GetNumber();这样的写法是不严谨的写法.由于TestClass是模板.模板是编译器生成代码的.按道理必须指定类型.如果没有类型.生成的子类又是指向哪里呢?
假如写法都写成
return TestTClass<int>::GetNumber();这样就不会发生这样的问题.据说GCC像上边的写法是编译不过去的.