这是一个非常难以发现的细微错误示例,由非直观的类型推导引起。程序员从 NewValue() 函数中的模板参数类型推导中期望“var2”的类型为“derived2”。实际发生的是 var2 的推导类型是基类“derived1”。如果您在派生类中覆盖了 ConvertValue() 虚函数,那么它会按预期编译和工作。
我放入编译器中断行只是为了演示类型不匹配。问题是 NewValue<> 用于许多地方,在这些地方,意外的类型推导干净利落地给出了意外的结果。此外,程序员希望能够只继承基类成员函数“ConvertValue()”,而不必为了让 NewValue<> 按预期工作而在每个派生类中重载它。
这是编译器正确解释还是编译器错误?
class base
{
int x;
public:
base() : x(10){}
int value() const { return x; }
void value( int val ) { x = val; }
};
class derived1 : public base
{
public:
virtual void ConvertValue( int x) { value( Factor()*x); }
virtual int Factor() const { return 2; }
};
class derived2 : public derived1
{
public:
//virtual void ConvertValue( int x) { value( Factor()*x); }
virtual int Factor() const { return 3; }
};
template<typename T>
T NewValue( void (T::*unitsFunc)(int), int value)
{
T obj;
(obj.*unitsFunc)(value);
return obj;
}
int _tmain(int argc, _TCHAR* argv[])
{
auto var1 = NewValue( &derived1::ConvertValue, 10 );
auto var2 = NewValue( &derived2::ConvertValue, 10 );
std::cout << "Test type deduction from virtual member function" << std::endl << std::endl
<< "This should have value of 20: " << var1.value() << std::endl
<< "This should have value of 30: " << var2.value() << std::endl
<< (var2.value() == 30 ? "CORRECT" : "INCORRECT - bad type deduction") << std::endl << std::endl ;
// this will not compile because NewValue<>() is returning type "derived1" instead of "derived2"
derived2 test = NewValue( &derived2::ConvertValue, 10 );
return 0;
}