2015-02-09 39 views
3

在重構一個相當龐大的代碼庫的過程中,我的編譯器提出了一個很好的方式來誤解我。這就是我講的一個小例子:C++通過模板和虛函數實現瘋狂

​​

鐺3.6,GCC 4.7,GCC 4.8和gcc 4.9所有的標記化 「b.get(7)」 作爲b.get之間」比較運算符「和」char「。

template-test.cpp: In function ‘int main(int, char**)’: 
template-test.cpp:16:17: error: invalid use of non-static member function 
    std::cout << b.get<char>(7) << std::endl; 
       ^
template-test.cpp:16:21: error: expected primary-expression before ‘char’ 
    std::cout << b.get<char>(7) << std::endl; 
        ^

(這是GCC 4.9,別人說類似的東西)

難道這工作?

我發現的解決方法是在基類和派生類中聲明模板「get」。

回答

9

派生類中的名稱get將名稱get隱藏在基類中。因此,在執行名稱查找時找不到函數模板get(),編譯器只能按照您看到的方式解釋這些標記。

您可以使用using聲明在Bar類修復:

class Bar : public Foo { 
public: 
    using Foo::get; 
// ^^^^^^^^^^^^^^^ 
    virtual int get() { return 3; } 
}; 

這裏是一個live demo on Coliru

如果不能修改的Bar的定義,因爲它不是你的控制之下,我想你可以調用資格get()

std::cout << f.Foo::get<char>(7) << std::endl; // get() template is found now. 

了現場演示見here。另一種選擇是通過執行指針或引用調用Foo

Bar b; 
Foo& f = b; 
std::cout << f.get<char>(7) << std::endl; // get() template is found now. 

再次,live example

+0

這個「重載到基類」是我聽說過的,但顯然沒有經常考慮。感謝您的教訓。 – 2015-02-09 17:34:53

+0

@PhilippT:我猜你可以搜索「名稱隱藏」以瞭解更多信息。歡呼:) – 2015-02-09 17:35:27

+0

如何'std :: cout << b.Foo::(7)<< std :: endl;'? – 2015-02-09 17:44:01