2012-06-18 25 views
1
#include <list> 
using std::list; 
class foo { ... 
class bar : public foo { ... 
static void print_all(list<foo*> &L) { ... 
list<foo*> LF; 
list<bar*> LB; 
... 
print_all(LF); // works fine 
print_all(LB); // static semantic error 

我想我知道爲什麼編譯器不會允許第二個調用。任何人都可以舉例說明如果編譯器接受這種類型的調用會發生什麼壞事?使用類的編譯器的行爲

+0

我喜歡這類問題 – zinking

回答

2

代碼中有兩種不同的事情,有不同的解釋。第一個問題是模板的不同實例是不相關的,即使實例化類型是相關的。在這種特殊情況下std::list<foo*>std::list<bar*>沒有任何關係,即使foobar的基數。這是語言設計的一部分,什麼都不能做。

第二個問題,這不是編譯器抱怨的問題,一般而言,容器derived不能用作容器base的引用。這是@templatetypedef長大 - 但再次的問題,這是不是在代碼中的問題,這將是一個不同的例子:

void f(base** p); 
int main() { 
    derived *d; 
    f(&d);   // error 
} 

在這種情況下,出現的問題是,作爲@templatetypedef指出使用指針/容器derived代替指針/容器到base以非常量方式容易出錯,因爲您可以在指針/容器上存儲非derived類型。

3

當然!如果print_all這麼做:

L.push_back(new Foo); 

現在,您的Bar指針列表中有一個指向Foo對象的指針,它不是Bar。如果您嘗試調用Bar中不存在的方法,您將會遇到某種嚴重的運行時問題,因爲該方法不存在於Foo對象中。

希望這會有所幫助!

+0

不同的模板實例化是不相關的類型。即使容器是'const'(因此你不能做任何違反約束的改變),它將不被允許。 –

+0

@ DavidRodriguez-dribeas-當然。我認爲OP的問題是爲什麼存在這個規則。 – templatetypedef

+0

我不太確定。有很多用途不是容器的模板。專業化允許完全不同的類型,並且無法將實例化類型與實例化模板之間的關係轉換。考慮到這些關係可能是繼承關係或其他關係(隱含地可以從第一個想到的)開始。還要注意,在語言(const-correctness)中有類似的例子,只要它是安全的,規範增加了靈活性,但是在這種特殊情況下沒有這樣做...... –