คำถามติดแท็ก virtual-functions

ในการเขียนโปรแกรมเชิงวัตถุฟังก์ชันเสมือนหรือวิธีเสมือนคือฟังก์ชันหรือวิธีการที่พฤติกรรมสามารถถูกแทนที่ภายในคลาสที่สืบทอดโดยฟังก์ชันที่มีลายเซ็นเดียวกัน แนวคิดนี้เป็นส่วนที่สำคัญมากของส่วนความหลากหลายของการเขียนโปรแกรมเชิงวัตถุ (OOP)

27
อะไรคือความแตกต่างระหว่างฟังก์ชั่นนามธรรมและฟังก์ชั่นเสมือนจริง?
อะไรคือความแตกต่างระหว่างฟังก์ชั่นนามธรรมและฟังก์ชั่นเสมือนจริง? แนะนำให้ใช้ virtual หรือ abstract ในกรณีใด วิธีใดเป็นวิธีที่ดีที่สุด

25
เหตุใดเราจึงต้องการฟังก์ชันเสมือนใน C ++
ฉันกำลังเรียนรู้ C ++ และฉันเพิ่งเข้าสู่ฟังก์ชั่นเสมือนจริง จากสิ่งที่ฉันได้อ่าน (ในหนังสือและออนไลน์) ฟังก์ชันเสมือนเป็นฟังก์ชันในคลาสพื้นฐานที่คุณสามารถแทนที่ในคลาสที่ได้รับ virtualแต่ก่อนหน้านี้ในหนังสือเล่มนี้เมื่อการเรียนรู้เกี่ยวกับมรดกพื้นฐานก็สามารถที่จะแทนที่ฟังก์ชั่นฐานในชั้นเรียนมาโดยไม่ต้องใช้ ดังนั้นสิ่งที่ฉันหายไปที่นี่ ฉันรู้ว่ามีฟังก์ชั่นเสมือนจริงมากขึ้นและดูเหมือนว่าจะมีความสำคัญดังนั้นฉันจึงต้องการชัดเจนว่ามันคืออะไร ฉันไม่สามารถหาคำตอบแบบตรงออนไลน์ได้

7
ฉันสามารถเรียกใช้ฟังก์ชันเสมือนของคลาสพื้นฐานได้หรือไม่ถ้าฉันลบล้างมัน?
ว่าฉันมีชั้นเรียนFooและBarตั้งค่าเช่นนี้: class Foo { public: int x; virtual void printStuff() { std::cout << x << std::endl; } }; class Bar : public Foo { public: int y; void printStuff() { // I would like to call Foo.printStuff() here... std::cout << y << std::endl; } }; ดังที่อธิบายไว้ในรหัสฉันต้องการที่จะสามารถเรียกฟังก์ชั่นระดับฐานที่ฉันเอาชนะ ใน Java มีsuper.funcname()ไวยากรณ์ เป็นไปได้ใน …

13
เทมเพลตฟังก์ชันสมาชิกระดับสามารถเป็นเสมือนได้หรือไม่?
ฉันได้ยินมาว่าแม่แบบฟังก์ชันคลาสสมาชิก C ++ ไม่สามารถเป็นเสมือนได้ มันเป็นเรื่องจริงเหรอ? หากพวกเขาสามารถเป็นเสมือนจริงตัวอย่างของสถานการณ์ที่จะใช้ฟังก์ชั่นดังกล่าวคืออะไร?

5
คำหลัก 'แทนที่' เป็นเพียงการตรวจสอบวิธีเสมือนจริงที่ถูกแทนที่หรือไม่
เท่าที่ฉันเข้าใจการแนะนำของoverrideคำหลักใน C ++ 11 ไม่มีอะไรมากไปกว่าการตรวจสอบเพื่อให้แน่ใจว่าฟังก์ชั่นการใช้งานเป็นการนำoverrideของvirtualฟังก์ชั่นในชั้นฐาน มันคืออะไร

9
คีย์เวิร์ด“ เสมือน” C ++ สำหรับฟังก์ชันในคลาสที่ได้รับ จำเป็นหรือไม่
ด้วยคำจำกัดความของโครงสร้างรับด้านล่าง ... struct A { virtual void hello() = 0; }; วิธีการ # 1: struct B : public A { virtual void hello() { ... } }; วิธีการ # 2: struct B : public A { void hello() { ... } }; มีความแตกต่างระหว่างสองวิธีในการแทนที่ฟังก์ชัน hello หรือไม่?

13
ฟังก์ชั่นเสมือนจริงแบบอินไลน์เป็นเรื่องที่ไม่สมเหตุสมผลหรือไม่?
ฉันได้รับคำถามนี้เมื่อฉันได้รับรหัสตรวจสอบความคิดเห็นว่าฟังก์ชั่นเสมือนไม่จำเป็นต้องอยู่ในบรรทัด ฉันคิดว่าฟังก์ชั่นเสมือนแบบอินไลน์อาจมีประโยชน์ในสถานการณ์ที่เรียกใช้ฟังก์ชันบนวัตถุโดยตรง แต่ข้อโต้แย้งโต้เถียงกันในใจของฉันก็คือ - ทำไมคนเราถึงต้องการกำหนดเสมือนและใช้วัตถุเพื่อเรียกวิธีการ เป็นการดีที่สุดที่จะไม่ใช้ฟังก์ชั่นเสมือนแบบอินไลน์เนื่องจากพวกมันแทบไม่เคยขยายเลย ข้อมูลโค้ดที่ฉันใช้สำหรับการวิเคราะห์: class Temp { public: virtual ~Temp() { } virtual void myVirtualFunction() const { cout<<"Temp::myVirtualFunction"<<endl; } }; class TempDerived : public Temp { public: void myVirtualFunction() const { cout<<"TempDerived::myVirtualFunction"<<endl; } }; int main(void) { TempDerived aDerivedObj; //Compiler thinks it's safe to expand the virtual …

6
คุณสามารถเขียนฟังก์ชัน / วิธีเสมือนใน Java ได้ไหม
เป็นไปได้ไหมที่จะเขียนเมธอดเสมือนใน Java เหมือนกับที่ใช้ใน C ++? หรือมีวิธีการ Java ที่เหมาะสมซึ่งคุณสามารถนำไปใช้ที่ก่อให้เกิดพฤติกรรมที่คล้ายกัน? ฉันขอตัวอย่างบางส่วนได้ไหม

15
ฟังก์ชันและประสิทธิภาพเสมือนจริง - C ++
ในการออกแบบชั้นเรียนของฉันฉันใช้คลาสนามธรรมและฟังก์ชันเสมือนอย่างกว้างขวาง ฉันรู้สึกว่าฟังก์ชันเสมือนมีผลต่อประสิทธิภาพ นี่คือเรื่องจริง? แต่ฉันคิดว่าความแตกต่างของประสิทธิภาพนี้ไม่สามารถสังเกตเห็นได้และดูเหมือนว่าฉันกำลังทำการเพิ่มประสิทธิภาพก่อนกำหนด ขวา?

12
ฟังก์ชันเสมือนจริงและ vtable ใช้งานอย่างไร
เราทุกคนรู้ว่าฟังก์ชันเสมือนจริงคืออะไรใน C ++ แต่จะใช้งานในระดับลึกได้อย่างไร vtable สามารถแก้ไขหรือเข้าถึงได้โดยตรงที่รันไทม์? vtable มีอยู่สำหรับทุกคลาสหรือเฉพาะที่มีฟังก์ชันเสมือนอย่างน้อยหนึ่งฟังก์ชัน? คลาสนามธรรมมีค่า NULL สำหรับตัวชี้ฟังก์ชันอย่างน้อยหนึ่งรายการหรือไม่? การมีฟังก์ชันเสมือนเดียวทำให้ทั้งชั้นเรียนช้าลงหรือไม่? หรือเฉพาะการเรียกใช้ฟังก์ชันที่เสมือนจริง? และความเร็วจะได้รับผลกระทบหรือไม่หากฟังก์ชันเสมือนถูกเขียนทับจริงหรือไม่หรือจะไม่มีผลตราบใดที่เป็นเสมือน

6
เหตุใดวิธีการเชื่อมต่อ C # จึงไม่ประกาศว่าเป็นนามธรรมหรือเสมือน
วิธีการ C # ในอินเทอร์เฟซถูกประกาศโดยไม่ใช้virtualคีย์เวิร์ดและแทนที่ในคลาสที่ได้รับโดยไม่ต้องใช้overrideคีย์เวิร์ด มีเหตุผลนี้หรือไม่? ฉันคิดว่ามันเป็นเพียงความสะดวกทางภาษาและเห็นได้ชัดว่า CLR รู้วิธีจัดการสิ่งนี้ภายใต้ฝาครอบ (วิธีการไม่ใช่เสมือนตามค่าเริ่มต้น) แต่มีเหตุผลทางเทคนิคอื่น ๆ หรือไม่? นี่คือ IL ที่คลาสที่ได้รับสร้างขึ้น: class Example : IDisposable { public void Dispose() { } } .method public hidebysig newslot virtual final instance void Dispose() cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } …

9
ต้นทุนประสิทธิภาพของการมีเมธอดเสมือนในคลาส C ++ คืออะไร?
การมีเมธอดเสมือนอย่างน้อยหนึ่งวิธีในคลาส C ++ (หรือคลาสพาเรนต์ใด ๆ ) หมายความว่าคลาสนั้นจะมีตารางเสมือนและอินสแตนซ์ทุกตัวจะมีตัวชี้เสมือน ดังนั้นค่าหน่วยความจำจึงค่อนข้างชัดเจน สิ่งที่สำคัญที่สุดคือต้นทุนหน่วยความจำในอินสแตนซ์ (โดยเฉพาะอย่างยิ่งหากอินสแตนซ์มีขนาดเล็กตัวอย่างเช่นหากอินสแตนซ์มีจุดมุ่งหมายเพื่อให้มีจำนวนเต็ม: ในกรณีนี้การมีตัวชี้เสมือนในทุกอินสแตนซ์อาจทำให้ขนาดของอินสแตนซ์เพิ่มขึ้นเป็นสองเท่า พื้นที่หน่วยความจำที่ใช้โดยตารางเสมือนจริงฉันเดาว่ามันมักจะเล็กน้อยเมื่อเทียบกับพื้นที่ที่ใช้โดยรหัสวิธีการจริง สิ่งนี้ทำให้ฉันเกิดคำถาม: มีต้นทุนประสิทธิภาพที่วัดได้ (เช่นผลกระทบด้านความเร็ว) สำหรับการสร้างวิธีการเสมือนจริงหรือไม่? จะมีการค้นหาในตารางเสมือนที่รันไทม์ทุกครั้งที่เรียกใช้เมธอดดังนั้นหากมีการเรียกใช้เมธอดนี้บ่อยมากและหากวิธีนี้สั้นมากก็อาจมีการตีประสิทธิภาพที่วัดได้? ฉันเดาว่ามันขึ้นอยู่กับแพลตฟอร์ม แต่มีใครใช้เกณฑ์มาตรฐานบ้างไหม เหตุผลที่ฉันถามคือฉันพบข้อผิดพลาดที่เกิดขึ้นเนื่องจากโปรแกรมเมอร์ลืมกำหนดวิธีการเสมือน นี่ไม่ใช่ครั้งแรกที่ฉันเห็นความผิดพลาดแบบนี้ และฉันก็คิดว่า: ทำไมเราถึงเพิ่มคีย์เวิร์ดเสมือนเมื่อจำเป็นแทนที่จะลบคีย์เวิร์ดเสมือนเมื่อเราแน่ใจอย่างยิ่งว่าไม่จำเป็น หากต้นทุนประสิทธิภาพต่ำฉันคิดว่าฉันจะแนะนำสิ่งต่อไปนี้ในทีมของฉันเพียงแค่ทำให้ทุกวิธีเสมือนเป็นค่าเริ่มต้นรวมทั้งตัวทำลายในทุกคลาสและลบออกเมื่อคุณต้องการเท่านั้น คุณฟังดูบ้าหรือเปล่า?

8
ข้อขัดข้อง "การเรียกฟังก์ชันเสมือนจริง" มาจากไหน
บางครั้งฉันสังเกตเห็นโปรแกรมที่ขัดข้องในคอมพิวเตอร์ของฉันโดยมีข้อผิดพลาด: "pure virtual function call" โปรแกรมเหล่านี้จะคอมไพล์ได้อย่างไรเมื่อวัตถุไม่สามารถสร้างคลาสนามธรรมได้

9
เหตุใด C # จึงใช้วิธีการไม่ใช่เสมือนโดยค่าเริ่มต้น
ต่างจาก Java เหตุใด C # จึงถือว่าเมธอดไม่ใช่ฟังก์ชันเสมือนตามค่าเริ่มต้น มีแนวโน้มที่จะเป็นปัญหาด้านประสิทธิภาพมากกว่าผลลัพธ์ที่เป็นไปได้อื่น ๆ หรือไม่? ฉันนึกถึงเมื่ออ่านย่อหน้าจาก Anders Hejlsberg เกี่ยวกับข้อดีหลายประการที่สถาปัตยกรรมที่มีอยู่กำลังนำออกมา แต่ผลข้างเคียงล่ะ? เป็นการแลกเปลี่ยนที่ดีจริงๆหรือไม่ที่จะมีวิธีการที่ไม่ใช่เสมือนโดยค่าเริ่มต้น?

9
แทนที่ฟังก์ชันเสมือน C ++ อย่างปลอดภัย
ฉันมีคลาสพื้นฐานที่มีฟังก์ชันเสมือนและฉันต้องการแทนที่ฟังก์ชันนั้นในคลาสที่ได้รับ มีวิธีใดบ้างที่จะทำให้คอมไพลเลอร์ตรวจสอบว่าฟังก์ชันที่ฉันประกาศในคลาสที่ได้รับมาแทนที่ฟังก์ชันในคลาสฐานหรือไม่? ฉันต้องการเพิ่มมาโครหรือสิ่งที่ช่วยให้มั่นใจได้ว่าฉันไม่ได้ประกาศฟังก์ชันใหม่โดยไม่ได้ตั้งใจแทนที่จะแทนที่ฟังก์ชันเก่า ใช้ตัวอย่างนี้: class parent { public: virtual void handle_event(int something) const { // boring default code } }; class child : public parent { public: virtual void handle_event(int something) { // new exciting code } }; int main() { parent *p = new child(); p->handle_event(1); } ที่นี่parent::handle_event()เรียกว่าแทนchild::handle_event()เนื่องจากวิธีการของเด็กพลาดการconstประกาศจึงประกาศวิธีการใหม่ นี่อาจเป็นการพิมพ์ผิดในชื่อฟังก์ชันหรือความแตกต่างเล็กน้อยในประเภทพารามิเตอร์ …

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.