2013-07-08 71 views
2

這是一個非常難以找到的細微錯誤的例子,這是由非直觀類型推理引起的。程序員希望「var2」是NewValue()函數中模板參數類型推導的類型「derived2」。實際發生的是var2的推導類型是 基類「derived1」。如果您在派生類中重寫了ConvertValue()虛函數,則它將編譯並按預期工作。從虛擬成員函數ptr中刪除類型(bug?)

爲了演示類型不匹配,我放入編譯器斷路器行。問題在於,許多地方使用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; 
} 

回答

1

不,這不是一個錯誤。每當您將&應用於&derived2::ConvertValue時,結果始終是指向聲明ConvertValue的類的成員的指針。這意味着&derived2::ConvertValue的結果類型爲void (derived1::*)(int)。 (這也是爲什麼當你在derived2中覆蓋它時,代碼編譯的原因)

但是,任何指向基類成員函數的指針都可以轉換爲指向派生類成員的指針。這是因爲derived2的所有實例都具有它們繼承的derived1::ConvertValue的成員函數。因此,您可以明確告訴編譯器將其轉換爲:

auto var2 = NewValue<derived2>(&derived2::ConvertValue, 10); 
+0

是的,這麼想。我希望類型演繹的力量可以用來保持語法清晰。我將不得不思考一些替代方案,因爲這些東西在大型代碼庫中隨處可見。謝謝 – user2562278