指針和對象切片
回答
是 - 指針base
需要能夠指從base
派生的任何類型的對象,並仍保持正確的類型派生對象(以及它的價值,也是同樣的道理與參考)。
「是的,它總是安全的。」他的問題承認不是「是」或「否」的答案。 –
這取決於你是否願意定義「切片」的鬆散程度。從某種意義上講,當你指向一個帶有基指針(或引用)的派生對象時,任何非虛函數都會被切分。例如:
class A {
void Print() { cout << "Class A\n"; }
};
class B : public A {
void DoB() {}
void Print() { cout << "Class B\n"; }
};
B b;
A* a = &b;
a->DoB(); // Won't compile!
a->Print(); // Prints "Class A", not "Class B"
,因爲我們使用的指針A
,所以編譯器不知道它可以對指針調用DoB
到DoB
調用不起作用。這樣,你就失去了B
的一部分,所以你可以把它當作切片的一種形式。
最後一行特別是一個稱爲「名稱隱藏」現象的例子。由於Print
未在基類中聲明爲virtual
,而我們的指針類型爲A
,編譯器不知道它應該調用B::Print
而不是A::Print
。
這個問題的一個重要例子進場時你的析構函數:
class A {
~A() {}
};
class B : public A {
std::vector<int> v;
};
A* a = new B;
delete a; // What happens to B::v? Undefined behaviour!
這裏,因爲析構函數沒有被標記爲virtual
,它被稱爲基類的在非虛擬上下文析構函數,這意味着B
的析構函數不會被調用。
哇,這是一個很好的答案。非常豐富。謝謝! –
- 1. 切片使用指針切片
- 2. Golang指針切片和陣列
- 3. 原始對象的C++指針和複製對象的指針
- 4. 句柄和指針對象
- 5. 指針和Java對象
- 6. 封裝和對象指針
- 7. 對象引用和對象指針
- 8. 無效指針指向對象指針
- 9. 指向類中對象的指針:push_back和指針衝突
- 10. 指針幫助,指向對象的指針和類
- 11. 當切片爲指針時按索引訪問切片
- 12. JS對象指針
- 13. fstream對象指針
- 14. FMOD對象指針
- 15. Java:NullException對象指針[]
- 16. JavaScript對象指針
- 17. C++對象指針
- 18. 指針轉到排序切片
- 19. 複製指針向量而不切片
- 20. 使用指針作爲切片的值
- 21. ,對象和指向對象的指針有什麼區別?
- 22. 對象解引用指針的指針?
- 23. 對象B和對象B對象的引用沒有指針
- 24. 的std ::對對象指針
- 25. Javascript對象排序和切片
- 26. 參考文獻和對象切片
- 27. 如何使用指向該切片的指針獲取切片項目
- 28. 不同對象的指針值和它的該指針
- 29. 面向對象的編程風格和指針指針
- 30. 指向const對象的指針自動轉換爲指向對象的指針
你可能會從這裏學到最好的:http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c – chris
我喜歡你如何提出矛盾的問題'指針可以是對象切片的受害者?'和'只要你使用了一個指針,你總是可以避免對象切片?'。這使得答案混淆。 – milleniumbug