VS2005中派生模板类的BUG

来源:互联网 发布:公安局网络安全管理岗 编辑:程序博客网 时间:2024/06/06 00:41

一般来说犯错误的都是开发者.VS的错误还是蛮少的.额..除了预编译头有时候会错误要Clean一下.

今天确实遇到了一个bug.查了半天.又写了好些测试代码.才把错误模型整理出来.

发现是在存在虚函数表时对于父类模板类的偏移计算错误.这句话说的挺绕口.

据说也和VS对代码限制较少有关.在GCC下是编译不过去的.


模型挺简单

template< class T >class TestTClass{public:Ti;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从TestTClass派生.并重写了两个函数.没有虚函数.这时没问题.测试代码

TestClasskClass;kClass.i = 3;kClass.m_vec.push_back( 1 );int iTest = kClass.GetNumber();int iSize = kClass.GetSize();


此时的iTest等于3. iSize等于1;


但如果将GetSize改成虚函数.

class TestClass : public TestTClass<int>{public:TestClass(){i = 1;}int GetNumber(){return TestTClass::GetNumber();}virtual int GetSize(){return TestTClass::GetSize();}};

问题就出来了.此时跟踪到TestTClass::GetNumber函数中发现this指针与父类的This指针已经不一样了.整个内存已经乱了.i和m_vec已经和父类不是同一个i和m_vec了.

TestClasskClass;kClass.i = 3;kClass.m_vec.push_back( 1 );int iTest = kClass.GetNumber();int iSize = kClass.GetSize();

此时的iTest和iSize大概都等于0;


如果是虚继承的话 like this:

class TestClass : virtual public TestTClass<int>
又没有问题.

根据现象分析.虚继承时父类包含有指向子类的指针.地址已经固定了.所以正确.由此推断可能是由于根据虚函数表计算子类地址时有错误.


但有一点必须指出.

return TestTClass::GetNumber();
这样的写法是不严谨的写法.由于TestClass是模板.模板是编译器生成代码的.按道理必须指定类型.如果没有类型.生成的子类又是指向哪里呢?

假如写法都写成

return TestTClass<int>::GetNumber();
这样就不会发生这样的问题.据说GCC像上边的写法是编译不过去的.





原创粉丝点击