ฉันควรใช้ตัวระบุข้อยกเว้นใน C ++ หรือไม่


123

ใน C ++ คุณสามารถระบุว่าฟังก์ชันอาจมีหรือไม่มีข้อยกเว้นโดยใช้ตัวระบุข้อยกเว้น ตัวอย่างเช่น:

void foo() throw(); // guaranteed not to throw an exception
void bar() throw(int); // may throw an exception of type int
void baz() throw(...); // may throw an exception of some unspecified type

ฉันสงสัยเกี่ยวกับการใช้งานจริงเนื่องจากสิ่งต่อไปนี้:

  1. คอมไพเลอร์ไม่ได้บังคับใช้ตัวระบุข้อยกเว้นอย่างเข้มงวด แต่อย่างใดดังนั้นประโยชน์จึงไม่มาก ตามหลักการแล้วคุณต้องการรับข้อผิดพลาดในการคอมไพล์
  2. หากฟังก์ชันละเมิดตัวระบุข้อยกเว้นฉันคิดว่าพฤติกรรมมาตรฐานคือการยุติโปรแกรม
  3. ใน VS.Net ถือว่าการโยน (X) เป็นการโยน (... ) ดังนั้นการยึดมั่นในมาตรฐานจึงไม่แข็งแรง

คุณคิดว่าควรใช้ตัวระบุข้อยกเว้นหรือไม่?
โปรดตอบด้วย "ใช่" หรือ "ไม่" และระบุเหตุผลบางประการเพื่อให้เหตุผลสำหรับคำตอบของคุณ


7
"throw (... )" ไม่ใช่ C ++ มาตรฐาน ฉันเชื่อว่ามันเป็นส่วนเสริมในคอมไพเลอร์บางตัวและโดยทั่วไปมีความหมายเหมือนกับไม่มีข้อกำหนดยกเว้น
Richard Corden

คำตอบ:


97

เลขที่

นี่คือตัวอย่างหลายประการว่าทำไม:

  1. โค้ดเทมเพลตไม่สามารถเขียนด้วยข้อกำหนดข้อยกเว้น

    template<class T>
    void f( T k )
    {
         T x( k );
         x.x();
    }
    

    สำเนาอาจโยนการส่งผ่านพารามิเตอร์อาจโยนและx()อาจทำให้เกิดข้อยกเว้นที่ไม่รู้จัก

  2. ข้อกำหนดข้อยกเว้นมักจะห้ามไม่ให้มีการขยาย

    virtual void open() throw( FileNotFound );

    อาจพัฒนาเป็น

    virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );

    คุณสามารถเขียนเป็น

    throw( ... )

    อย่างแรกไม่สามารถขยายได้อย่างที่สองมีความทะเยอทะยานมากเกินไปและอันที่สามคือสิ่งที่คุณหมายถึงเมื่อคุณเขียนฟังก์ชันเสมือนจริง

  3. รหัสเดิม

    เมื่อคุณเขียนโค้ดที่อาศัยไลบรารีอื่นคุณจะไม่รู้จริงๆว่ามันจะทำอะไรได้บ้างเมื่อมีสิ่งผิดปกติเกิดขึ้น

    int lib_f();
    
    void g() throw( k_too_small_exception )
    { 
       int k = lib_f();
       if( k < 0 ) throw k_too_small_exception();
    }
    

    gจะยุติเมื่อlib_f()ขว้าง นี่คือ (ในกรณีส่วนใหญ่) ไม่ใช่สิ่งที่คุณต้องการจริงๆ std::terminate()ไม่ควรถูกเรียก เป็นการดีกว่าเสมอที่จะปล่อยให้แอปพลิเคชันหยุดทำงานโดยมีข้อยกเว้นที่ไม่สามารถจัดการได้ซึ่งคุณสามารถเรียกคืนสแต็กแทร็กได้ดีกว่าการตายแบบเงียบ / รุนแรง

  4. เขียนโค้ดที่ส่งคืนข้อผิดพลาดทั่วไปและพ่นในโอกาสพิเศษ

    Error e = open( "bla.txt" );
    if( e == FileNotFound )
        MessageUser( "File bla.txt not found" );
    if( e == AccessDenied )
        MessageUser( "Failed to open bla.txt, because we don't have read rights ..." );
    if( e != Success )
        MessageUser( "Failed due to some other error, error code = " + itoa( e ) );
    
    try
    {
       std::vector<TObj> k( 1000 );
       // ...
    }
    catch( const bad_alloc& b )
    { 
       MessageUser( "out of memory, exiting process" );
       throw;
    }
    

อย่างไรก็ตามเมื่อห้องสมุดของคุณมีข้อยกเว้นของคุณเองคุณสามารถใช้ข้อกำหนดข้อยกเว้นเพื่อระบุเจตนาของคุณได้


1
ใน 3 ในทางเทคนิคจะเป็น std :: ไม่คาดคิดไม่ std :: สิ้นสุด แต่เมื่อมีการเรียกใช้ฟังก์ชันนี้ค่าเริ่มต้นจะเรียกใช้ abort () สิ่งนี้สร้างการถ่ายโอนข้อมูลหลัก สิ่งนี้แย่กว่าข้อยกเว้นที่ไม่สามารถจัดการได้อย่างไร? (ซึ่งโดยพื้นฐานแล้วสิ่งเดียวกัน)
Greg Rogers

6
@Greg Rogers: ข้อยกเว้นที่ไม่ได้จับคู่ยังคงคลี่คลายสแต็ก ซึ่งหมายความว่าผู้ทำลายจะถูกเรียก และในผู้ทำลายล้างเหล่านั้นสามารถทำได้หลายอย่างเช่น: ทรัพยากรถูกปลดปล่อยอย่างถูกต้องบันทึกถูกเขียนอย่างถูกต้องกระบวนการอื่น ๆ จะถูกบอกว่ากระบวนการปัจจุบันหยุดทำงานเป็นต้นสรุปก็คือ RAII
paercebal

คุณทิ้งไว้: สิ่งนี้ครอบคลุมทุกอย่างในtry {...} catch (<specified exceptions>) { <do whatever> } catch (...) { unexpected(); ]โครงสร้างได้อย่างมีประสิทธิภาพไม่ว่าคุณจะต้องการลองบล็อกที่นั่น
David Thornley

4
@paercebal นั่นไม่ถูกต้อง เป็นการใช้งานที่กำหนดไว้ว่าจะเรียกใช้ตัวทำลายล้างโดยไม่มีข้อยกเว้นหรือไม่ สภาพแวดล้อมส่วนใหญ่ไม่คลายตัวทำลายสแตก / รันหากไม่พบข้อยกเว้น หากคุณต้องการพกพาให้แน่ใจว่าผู้ทำลายของคุณทำงานได้แม้จะมีการโยนข้อยกเว้นและไม่ได้รับการจัดการ (นี่เป็นค่าที่น่าสงสัย) คุณต้องเขียนโค้ดของคุณเช่นtry { <<...code...>> } catch(...) /* stack guaranteed to be unwound here and dtors run */ { throw; /* pass it on to the runtime */ }
Logan Capaldo

" มันจะดีกว่าเสมอที่จะปล่อยให้แอปพลิเคชันหยุดทำงานโดยมีข้อยกเว้นที่ไม่สามารถจัดการได้ซึ่งคุณสามารถดึงสแต็กแทร็กกลับมาได้ดีกว่าการตายอย่างเงียบ ๆ / รุนแรง " "ความผิดพลาด" จะดีกว่าการเรียกแบบใหม่ได้terminate()อย่างไร ทำไมไม่โทรหาabort()?
ซอกแซก

42

หลีกเลี่ยงข้อกำหนดข้อยกเว้นใน C ++ เหตุผลที่คุณให้ไว้ในคำถามของคุณเป็นการเริ่มต้นที่ดีว่าทำไม

ดูสมุนไพรซัทเทอ"มองในทางปฏิบัติที่ยกเว้นข้อมูลจำเพาะ"


3
@awoodland: การใช้ 'dynamic-exception-specification' ( throw(optional-type-id-list)) เลิกใช้แล้วใน C ++ 11 พวกเขายังคงอยู่ในมาตรฐาน แต่ฉันเดาว่ามีการส่งสัญญาณเตือนว่าควรพิจารณาการใช้งานอย่างรอบคอบ C ++ 11 เพิ่มnoexceptข้อกำหนดและตัวดำเนินการ ฉันไม่ทราบรายละเอียดเพียงพอเกี่ยวกับnoexceptการแสดงความคิดเห็น บทความนี้ดูเหมือนจะมีรายละเอียดค่อนข้างมาก: akrzemi1.wordpress.com/2011/06/10/using-noexcept และ Dietmar Kühlมีบทความใน Overload Journal ฉบับเดือนมิถุนายน 2011: Accu.org/var/uploads/journals/overload103.pdf
Michael Burr

@MichaelBurr เท่านั้นthrow(something)ถือว่าไร้ประโยชน์และเป็นความคิดที่ไม่ดี throw()มีประโยชน์
ซอกแซก

" นี่คือสิ่งที่หลายคนคิดว่าข้อกำหนดของข้อยกเว้นทำ: สัญลักษณ์แสดงหัวข้อย่อยรับประกันว่าฟังก์ชันจะแสดงเฉพาะข้อยกเว้นที่ระบุไว้ (อาจไม่มี) bullet เปิดใช้งานการเพิ่มประสิทธิภาพคอมไพเลอร์ตามความรู้ที่ระบุเฉพาะข้อยกเว้นที่ระบุไว้ (อาจไม่มี) ความคาดหวังข้างต้นคือ อีกครั้งหลอกลวงใกล้จะถูก "ไม่เหนือความคาดหมายถูกต้องอย่างแน่นอน
ซอกแซก

14

ฉันคิดว่าตัว
ระบุข้อยกเว้นมาตรฐาน (สำหรับ C ++) เป็นการทดลองในมาตรฐาน C ++ ซึ่งส่วนใหญ่ล้มเหลว
ข้อยกเว้นคือไม่มีตัวระบุการโยนจะมีประโยชน์ แต่คุณควรเพิ่มบล็อก try catch ที่เหมาะสมภายในเพื่อให้แน่ใจว่ารหัสตรงกับตัวระบุ เฮิร์บซัทเทอร์มีหน้าเรื่อง ก๊อต 82

นอกจากนี้ฉันคิดว่ามันคุ้มค่าที่จะอธิบายการรับประกันข้อยกเว้น

สิ่งเหล่านี้เป็นเอกสารโดยทั่วไปเกี่ยวกับสถานะของวัตถุที่ได้รับผลกระทบจากข้อยกเว้นที่หลีกเลี่ยงวิธีการบนวัตถุนั้น น่าเสียดายที่คอมไพเลอร์ไม่ได้บังคับหรือกล่าวถึงเป็นอย่างอื่น
เพิ่มและข้อยกเว้น

การรับประกันข้อยกเว้น

ไม่รับประกัน:

ไม่มีการรับประกันเกี่ยวกับสถานะของอ็อบเจ็กต์หลังจากที่มีการยกเว้น
หลีกเลี่ยงเมธอดในสถานการณ์เหล่านี้อ็อบเจ็กต์ไม่ควรใช้อีกต่อไป

การรับประกันขั้นพื้นฐาน:

ในเกือบทุกสถานการณ์นี่ควรเป็นวิธีการรับประกันขั้นต่ำที่มีให้
สิ่งนี้รับประกันว่าสถานะของวัตถุได้รับการกำหนดไว้อย่างดีและยังสามารถใช้งานได้อย่างสม่ำเสมอ

การรับประกันที่แข็งแกร่ง: (aka Transactional Guarantee)

สิ่งนี้รับประกันได้ว่าวิธีการจะเสร็จสมบูรณ์
หรือข้อยกเว้นจะถูกโยนและสถานะของวัตถุจะไม่เปลี่ยนแปลง

ไม่รับประกันการโยน:

วิธีนี้รับประกันว่าไม่มีข้อยกเว้นใด ๆ ที่ได้รับอนุญาตให้เผยแพร่ออกจากวิธีการ
ผู้ทำลายทั้งหมดควรให้การรับประกันนี้
| หมายเหตุหากข้อยกเว้นหนีตัวทำลายในขณะที่ข้อยกเว้นกำลังแพร่กระจาย
| แอปพลิเคชันจะสิ้นสุดลง


การรับประกันเป็นสิ่งที่โปรแกรมเมอร์ C ++ ทุกคนต้องรู้ แต่ดูเหมือนว่าฉันจะไม่เกี่ยวข้องกับข้อกำหนดข้อยกเว้น
David Thornley

1
@David Thornley: ฉันเห็นการรับประกันว่าข้อกำหนดข้อยกเว้นควรเป็นอย่างไร (เช่นวิธีการที่มี G ที่แข็งแกร่งไม่สามารถเรียกวิธีที่มี G พื้นฐานโดยไม่มีการป้องกัน) น่าเสียดายที่ฉันไม่แน่ใจว่ามีการกำหนดไว้ดีพอที่จะบังคับใช้ในลักษณะที่เป็นประโยชน์สำหรับคอมไพเลอร์
Martin York

" นี่คือสิ่งที่หลายคนคิดว่าข้อกำหนดข้อยกเว้นทำ: - รับประกันว่าฟังก์ชันจะแสดงเฉพาะข้อยกเว้นที่ระบุไว้เท่านั้น (อาจไม่มี) - เปิดใช้งานการเพิ่มประสิทธิภาพคอมไพเลอร์ตามความรู้ที่ระบุเฉพาะข้อยกเว้นที่ระบุไว้ (อาจไม่มี) ความคาดหวังข้างต้นคือ อีกครั้ง deceptively ใกล้เคียงกับการที่ถูกต้อง. "จริงๆแล้วทั้งสองอยู่ตรงด้านขวา
ซอกแซก

@curiousguy นั่นเป็นวิธีที่ Java ทำเพราะมีการบังคับใช้การตรวจสอบในเวลาคอมไพล์ C ++ คือการตรวจสอบรันไทม์ ดังนั้น: Guarantee that functions will only throw listed exceptions (possibly none). ไม่จริง. มันรับประกันได้ว่าหากฟังก์ชันนี้มีข้อยกเว้นเหล่านี้แอปพลิเคชันจะยุติ Enable compiler optimizations based on the knowledge that only listed exceptions (possibly none) will be thrownไม่สามารถทำได้ เพราะฉันแค่ชี้ให้เห็นว่าคุณไม่สามารถรับประกันได้ว่าข้อยกเว้นจะไม่ถูกโยนทิ้ง
Martin York

1
@LokiAstari "นั่นเป็นวิธีที่ Java ทำเพราะการตรวจสอบถูกบังคับใช้ในเวลาคอมไพล์ _" ข้อกำหนดข้อยกเว้นของ Java เป็นการทดลองที่ล้มเหลว Java ไม่มีข้อกำหนดข้อยกเว้นที่มีประโยชน์ที่สุด: throw()(ไม่โยน) " มันรับประกันได้ว่าหากฟังก์ชันนี้มีข้อยกเว้นเหล่านี้แอปพลิเคชันจะยุติ " ไม่ "ไม่จริง" หมายถึงจริง ไม่มีการรับประกันใน C ++ ว่าฟังก์ชันจะไม่ถูกเรียกterminate()เลยทีเดียว " เพราะฉันแค่ชี้ให้เห็นว่าคุณไม่สามารถรับประกันได้ว่าข้อยกเว้นจะไม่ถูกโยนทิ้ง " คุณรับประกันว่าฟังก์ชันจะไม่โยน ซึ่งเป็นสิ่งที่คุณต้องการ
ซอกแซก

8

gcc จะส่งเสียงเตือนเมื่อคุณละเมิดข้อกำหนดข้อยกเว้น สิ่งที่ฉันทำคือใช้มาโครเพื่อใช้ข้อกำหนดข้อยกเว้นเฉพาะในโหมด "ผ้าสำลี" คอมไพล์อย่างชัดแจ้งเพื่อตรวจสอบว่าข้อยกเว้นนั้นสอดคล้องกับเอกสารของฉัน


7

ตัวระบุข้อยกเว้นที่มีประโยชน์เพียงอย่างเดียวคือ "throw ()" เช่นเดียวกับ "ไม่โยน"


2
คุณช่วยเพิ่มเหตุผลที่เป็นประโยชน์ได้ไหม
buti-oxa

2
ทำไมมันไม่มีประโยชน์? ไม่มีอะไรจะมีประโยชน์ไปกว่าการรู้ว่าฟังก์ชันบางอย่างจะไม่เริ่มต้นยกเว้นซ้ายขวาและตรงกลาง
Matt Joiner

1
โปรดดูการอภิปรายของ Herb Sutter ที่อ้างถึงในคำตอบของ Michael Burr สำหรับคำอธิบายโดยละเอียด
Harold Ekst จาก

4

ข้อกำหนดข้อยกเว้นไม่ใช่เครื่องมือที่มีประโยชน์อย่างยิ่งใน C ++ อย่างไรก็ตามมี / มี / การใช้งานที่ดีสำหรับพวกเขาหากรวมกับ std :: ไม่คาดคิด

สิ่งที่ฉันทำในบางโปรเจ็กต์คือโค้ดที่มีข้อกำหนดข้อยกเว้นจากนั้นเรียกใช้ set_un ไม่คาดคิด () ด้วยฟังก์ชันที่จะทำให้เกิดข้อยกเว้นพิเศษสำหรับการออกแบบของฉันเอง ข้อยกเว้นนี้ในการสร้างจะได้รับ backtrace (ในลักษณะเฉพาะแพลตฟอร์ม) และได้มาจาก std :: bad_exception (เพื่อให้สามารถเผยแพร่ได้หากต้องการ) ถ้ามันทำให้เกิดการเรียก terminate () ตามปกติ backtrace จะถูกพิมพ์โดย what () (เช่นเดียวกับข้อยกเว้นดั้งเดิมที่ทำให้เกิด; ไม่ยากที่จะค้นหา) ดังนั้นฉันจึงได้รับข้อมูลว่าสัญญาของฉันอยู่ที่ไหน ละเมิดเช่นข้อยกเว้นของห้องสมุดที่ไม่คาดคิดเกิดขึ้น

ถ้าฉันทำเช่นนี้ฉันจะไม่อนุญาตให้เผยแพร่ข้อยกเว้นของไลบรารี (ยกเว้น std) และได้รับข้อยกเว้นทั้งหมดของฉันจาก std :: exception ถ้าห้องสมุดตัดสินใจที่จะโยนฉันจะจับและแปลงเป็นลำดับชั้นของฉันเองทำให้ฉันสามารถควบคุมรหัสได้ตลอดเวลา ฟังก์ชัน Templated ที่เรียกใช้ฟังก์ชันตามควรหลีกเลี่ยงข้อกำหนดข้อยกเว้นด้วยเหตุผลที่ชัดเจน แต่ก็เป็นเรื่องยากที่จะมีอินเทอร์เฟซฟังก์ชันเทมเพลตพร้อมรหัสไลบรารีอยู่แล้ว (และมีห้องสมุดเพียงไม่กี่แห่งที่ใช้เทมเพลตอย่างมีประโยชน์)


3

หากคุณกำลังเขียนโค้ดที่จะถูกใช้โดยผู้ที่ต้องการดูการประกาศฟังก์ชันมากกว่าความคิดเห็นใด ๆ ที่อยู่รอบ ๆ ข้อกำหนดจะบอกพวกเขาว่าพวกเขาต้องการข้อยกเว้นใด

มิฉะนั้นฉันจะไม่พบว่ามีประโยชน์อย่างยิ่งที่จะใช้อะไร แต่throw()เพื่อระบุว่าไม่มีข้อยกเว้นใด ๆ


3

ไม่หากคุณใช้มันและเกิดข้อยกเว้นที่คุณไม่ได้ระบุไม่ว่าจะโดยรหัสของคุณหรือรหัสที่เรียกโดยรหัสของคุณพฤติกรรมเริ่มต้นคือการยุติโปรแกรมของคุณทันที

นอกจากนี้ฉันเชื่อว่าการใช้งานได้เลิกใช้แล้วในร่างมาตรฐาน C ++ 0x ปัจจุบัน


3

ข้อกำหนด "throw ()" ช่วยให้คอมไพลเลอร์ดำเนินการเพิ่มประสิทธิภาพบางอย่างเมื่อทำการวิเคราะห์การไหลของโค้ดหากทราบว่าฟังก์ชันนั้นจะไม่มีข้อยกเว้น (หรืออย่างน้อยก็สัญญาว่าจะไม่มีข้อยกเว้น) Larry Osterman พูดถึงเรื่องนี้สั้น ๆ ที่นี่:

http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx


2

โดยทั่วไปฉันจะไม่ใช้ตัวระบุข้อยกเว้น อย่างไรก็ตามในกรณีที่หากมีข้อยกเว้นอื่น ๆ เกิดขึ้นจากฟังก์ชันที่มีปัญหาซึ่งโปรแกรมจะไม่สามารถแก้ไขได้อย่างแน่นอนก็จะมีประโยชน์ ในทุกกรณีตรวจสอบให้แน่ใจว่าได้จัดทำเอกสารอย่างชัดเจนว่าอาจเกิดข้อยกเว้นใดจากฟังก์ชันนั้น

ใช่ลักษณะการทำงานที่คาดไว้ของข้อยกเว้นที่ไม่ได้ระบุซึ่งถูกโยนออกจากฟังก์ชันที่มีตัวระบุข้อยกเว้นคือการเรียกใช้ terminate ()

ฉันจะสังเกตด้วยว่า Scott Meyers กล่าวถึงเรื่องนี้ใน C ++ ที่มีประสิทธิภาพมากขึ้น C ++ ที่มีประสิทธิภาพและ C ++ ที่มีประสิทธิภาพของเขาเป็นหนังสือที่แนะนำเป็นอย่างยิ่ง


2

ใช่ถ้าคุณอยู่ในเอกสารภายใน หรืออาจจะเขียนบรรณารักษ์ที่คนอื่นจะใช้เพื่อให้พวกเขาสามารถบอกได้ว่าเกิดอะไรขึ้นโดยไม่ต้องศึกษาเอกสาร การโยนหรือไม่โยนถือเป็นส่วนหนึ่งของ API เกือบจะเหมือนกับมูลค่าที่ส่งคืน

ฉันยอมรับว่าพวกเขาไม่ได้มีประโยชน์จริงๆสำหรับการบังคับใช้สไตล์ Java ที่ถูกต้องในคอมไพเลอร์ แต่ก็ดีกว่าไม่มีอะไรเลยหรือแสดงความคิดเห็นส่งเดช


2

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


0

จากบทความ:

http://www.boost.org/community/exception_safety.html

“ เป็นที่ทราบกันดีว่าเป็นไปไม่ได้ที่จะเขียนคอนเทนเนอร์ทั่วไปที่ปลอดภัยเป็นพิเศษ” คำกล่าวอ้างนี้มักจะได้ยินโดยอ้างอิงถึงบทความของ Tom Cargill [4] ซึ่งเขาได้สำรวจปัญหาเรื่องความปลอดภัยที่เป็นข้อยกเว้นสำหรับเทมเพลตสแต็กทั่วไป ในบทความของเขาคาร์กิลล์ตั้งคำถามที่เป็นประโยชน์มากมาย แต่น่าเสียดายที่ไม่สามารถนำเสนอวิธีแก้ปัญหาของเขาได้ 1 เขาสรุปด้วยการแนะนำว่าวิธีแก้ปัญหาอาจเป็นไปไม่ได้ น่าเสียดายที่หลายคนอ่านบทความของเขาว่าเป็น "หลักฐาน" ของการคาดเดานั้น เนื่องจากมีการเผยแพร่จึงมีตัวอย่างของส่วนประกอบทั่วไปที่ปลอดภัยเป็นพิเศษมากมายรวมถึงคอนเทนเนอร์ไลบรารีมาตรฐาน C ++

และแน่นอนฉันสามารถคิดวิธีที่จะทำให้ข้อยกเว้นคลาสเทมเพลตปลอดภัย เว้นแต่คุณจะไม่สามารถควบคุมคลาสย่อยทั้งหมดได้คุณก็อาจมีปัญหาอยู่ดี ในการทำเช่นนี้สามารถสร้าง typedefs ในคลาสของคุณซึ่งกำหนดข้อยกเว้นที่เกิดจากคลาสเทมเพลตต่างๆ สิ่งนี้คิดว่าปัญหาอยู่ที่การแก้ไขปัญหาในภายหลังเมื่อเทียบกับการออกแบบตั้งแต่เริ่มต้นและฉันคิดว่ามันเป็นค่าใช้จ่ายที่เป็นอุปสรรคที่แท้จริง


-2

ข้อกำหนดข้อยกเว้น = ขยะโปรดสอบถามนักพัฒนา Java ที่อายุเกิน 30 ปี


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