2015-06-15 24 views
2

我已經閱讀了許多關於這個問題的不同文章,數組不是被多態處理,而是應該使用指針數組,而且它背後的理由對我來說很清楚。如何使用多態指針的數組或向量?

但是,我無法找到它是如何完成的例子,我似乎無法得到它的工作。考慮下面的代碼:

#include <vector> 

class Base 
{ 
    public: 
     Base(); 
     virtual ~Base(); 
}; 

class Derived : Base 
{ 
    public: 
     Derived(); 
     ~Derived(); 
}; 

void foo(std::vector<Base*>) 
{ 
    // do something 
} 

int main() 
{ 
    std::vector<Derived*> bar; 
    foo(bar); 

    return 0; 
} 

編譯此提供錯誤消息

could not convert 'bar' from 'std::vector<Derived*>' to 'std::vector<Base*> 

我缺少的東西或者是設計甚至是根本性的缺陷?提前致謝。

回答

6

std::vector<Derived*>std::vector<Base*>是不同的類型,它們之間沒有轉換。但它看起來像你需要的是

std::vector<Base*> bar; 
foo(bar); 

即讓多態性工作在向量的元素的水平。

但是,請注意,爲了在通常意義上的使用多態,Derived必須從Base公開繼承

class Derived : public Base 
       ^^^^^^ 

struct Derived : Base 
1

我缺少的東西或設計是否有根本的缺陷?

std::vector<Derived*>的對象不能自動轉換爲std::vector<Base*>。他們是兩種完全不同的類型。

我能想到的下列選項來解決這個問題:

  1. 變化foo接受std::vector<Derived*>

    void foo(std::vector<Derived*>) 
    { 
        // do something 
    } 
    
  2. foo更改爲函數模板。

    template <typename T> 
    void foo(std::vector<T*>) 
    { 
        // do something with the implicit understanding that 
        // T is derived from Base. 
    } 
    
  3. 將呼叫代碼更改爲使用std::vector<Base*>

2

要完成juanchopanza的答案,這是你如何使用您的std::vector<Derived*>

void itemfoo(Base* item) 
{ 
    // do something 
} 

template<typename Iter> 
void foo(Iter begin, Iter end) { 
    // do stuff per element 
    while(begin != end) 
     itemfoo(*begin++); 
} 

int main() 
{ 
    std::vector<Derived*> bar; 
    foo(bar.begin(), bar.end()); 

    return 0; 
} 

,如果你需要在整個範圍內做手術,做它作爲Base*,那麼你可以這樣做:

void foo(Base** begin, Base** end) { 
    // do stuff on range [begin, end) 
} 

int main() 
{ 
    std::vector<Derived*> bar; 
    if(bar.empty()) 
     foo(nullptr, nullptr); // or however you handle the empty range 
    else 
     foo(&bar[0], &bar[0] + bar.size()); 

    return 0; 
}