2017-04-16 118 views
0
#include <vector> 

class Base 
{ 
public: 
    virtual void foo() = 0; 
}; 

template<typename Bar> 
class Cloud : public Base 
{ 
public: 
    void foo() 
    { 
    } 
}; 

class Water 
{ 
}; 

int main() 
{ 
    Cloud<Water> cloud; 
    std::vector<Base> stuff; 
    stuff.push_back(cloud); 
} 

上面所示的代碼失敗與MSVC 14.1如下:爲什麼派生的模板類的函數沒有覆蓋非模板化的基類的純虛函數?

error C2259: 'Base': cannot instantiate abstract class 
note: due to following members: 
note: 'void Base::foo(void)': is abstract 

爲什麼Base::foo()仍然即使Cloud實現它的抽象?
我該如何實現這一點,Cloud仍然從Base派生,覆蓋foo()並保持與typename Bar模板?

回答

2

模板在這裏只是一個分心 - 它們與你的問題沒有任何關係。

std::vector<Base>包含Base對象,而不是引用,所以如果您嘗試任何派生的實例添加到它,它會嘗試執行切片,試圖實例從通過cloud一個Base。然而,除了不可能達到你想要的目標之外,這是不可能的,因爲Base是一個抽象類,所以不能存在直接的Base對象。

很可能你想要的是在保持多態行爲的同時將對象推向向量。爲此,您必須向基類指定指針的向量,並將指針指向元素 - 最有可能分配在堆上,並且有一些意味着處理它們的生命週期。一個簡單的(儘管可能不是最優的)解決方案可能有一個std::vector<std::shared_ptr<Base>>和分配給std::make_shared的推送對象。

+3

謝謝你很好解釋的答案!保持多態行爲絕對是我的本意。我決定使用'std :: unique_ptr'來代替,因爲我不需要引用計數。 – tambre

+1

@tambre在這種情況下,您需要爲'Base'提供一個虛擬析構函數。 –

4

功能是一個紅色的鯡魚:std::vector<Base>Base對象的矢量,因此push_back試圖從您的Cloud<Water>構建Base

改爲使用std::vector<std::unique_ptr<Base>>

+0

或者'std :: vector >'如果你不喜歡指針。 – Rakete1111

+0

@ Rakete1111你爲什麼不喜歡指針?他們和鹹菜很好。除了笑話之外,'std :: reference_wrapper '不會擁有與'std :: unique_ptr '或'Base'相同的所有權語義。 – Quentin

+0

沒錯,沒有想到這一點。我只是把它放在那裏:) – Rakete1111

相關問題