2014-10-01 48 views
0
class Base 
{ 
    bool a; 
}; 

class Derived : public Base 
{ 
    bool b; 
}; 

void main() 
{ 
    std::shared_ptr<Base> base(new Derived()); 
} 

所以在這個例子中,shared_ptr的原始指針將指向Base,NOT Derived的一個實例。我不明白。std :: shared_ptr的原始指針返回基地而不是派生的

class Base 
{ 
    virtual void foo() {} 
    bool a; 
}; 

class Derived : public Base 
{ 
    virtual void foo() {} 
    bool b; 
}; 

void main() 
{ 
    std::shared_ptr<Base> base(new Derived()); 
} 

但是在這種情況下,shared_ptr的原始指針指向Derived?我確定我錯過了一些東西。有人可以向我解釋爲什麼會發生這種情況嗎?

+1

指針在這兩種情況下指向「派生」實例。在這方面,共享指針與原始指針沒有區別。 – 2014-10-01 10:48:05

+2

你如何確定它指向調試器?如果基類沒有至少一個虛函數,則某些信息不會嵌入類中以確定其類型,並且調試器可能無法推斷其派生類型。 – 2014-10-01 10:49:27

+0

@NeilKirk即使類是多態的,我使用的調試器也不能推導出類型。(但是,當然,如果'Base'不是多態的,調試器就不可能知道它實際上是一個Derived'。 – 2014-10-01 13:46:56

回答

2

在第一個示例中,類沒有虛擬表,因爲沒有虛擬功能。 這意味着,由於shared_ptr需要一個靜態類型的Base,它將存儲一個Base。 第二種情況也存儲一個Base,但是存在一個虛擬表格可以讓你看到對象的動態類型是Derived。

+0

shared_ptr既不存儲基數也不派生。它存儲指針。 (1)這些指針指向什麼,(2)指針的類型是什麼,以及(3)在運行時執行哪些成員函數是三個不同的問題。 – 2014-10-01 11:00:13

+0

在這兩種情況下,指針都存儲一個指向「Base」的指針,它是「Derived」的子對象,它繼續存在。在第二種情況下'Base'是多態的這一事實使得訪問'Derived'變得更加容易和更自然,但是在兩種情況下存儲的和它指向的內容都是相同的。 – 2014-10-01 13:45:01

1

首先,使用std::shared_ptr這裏是一個紅色的鯡魚。在 這種情況下,std::shared_ptr和一個原始指針行爲 完全一樣。在這兩種情況下,表達式new Derived() 返回指向整個對象的Derived*。和在 這兩種情況下,使用它的指針初始化爲Base,無論是 原始指針或任何合理的設計,智能指針將 導致Derived*轉換爲一個Base*,其指向 到Base子對象在Derived。該Derived對象 仍然存在,但是,可以用幾種不同 方式訪問:通過虛擬功能,通過使用std::static_cast如果您使用std::dynamic_cast如果 Base是多態的(至少有一個虛函數),通過 100%確定指向 的對象實際上是Derived,可能還有一些我沒有想到的 。在你的第一種情況下,只有最後一種可能, 因爲在第一種情況下,Base不是多態。但是,在您的兩個 示例中,指針都指向Base,即 較大的子對象Derived

std::shared_ptr和原始 指針之間有一些差異。例如,在第一個示例中,將 std::shared_ptr<Base>替換爲Base*,並通過指針手動刪除 將導致未定義的行爲; std::shared_ptr有避免這種情況的額外複雜性。 (但 併發症並非沒有缺點,給Base 虛析構函數,因爲它應該有,然後進行 析構函數Derived私人的,出於某種奇怪的原因, 和你的第一個例子將無法編譯。)

相關問題