จับข้อผิดพลาดโดยตัวสร้างใน C ++ หรือไม่

ฉันมีคลาส foo (ซึ่งฉันไม่สามารถแก้ไขได้) มีคอนสตรัคเตอร์เพียงตัวเดียวที่รับอาร์กิวเมนต์เดียวดังนี้:

foo bar("Hello!");

เนื่องจาก Constructor สามารถส่งข้อผิดพลาดได้ ฉันจึงต้องการใช้การจัดการข้อผิดพลาด ความพยายามครั้งแรกของฉันคือ:

try {
    foo bar("Hello!");
}
catch {
    cerr << "Something went horribly wrong...";
    return -1;
}

อย่างไรก็ตาม ขณะนี้ foo อยู่ภายในขอบเขตของบล็อก try และไม่สามารถใช้ที่อื่นได้ ถ้าฉันเข้าใจสิ่งที่ถูกต้อง ฉันไม่สามารถประกาศวัตถุโดยไม่เตรียมใช้งาน ดังนั้นฉันสามารถประกาศ bar นอกบล็อก try ได้ แล้วฉันจะทำอย่างไรเพื่อตรวจจับข้อผิดพลาดที่ Constructor ส่งมา?

แก้ไข: เพื่อชี้แจงให้ชัดเจน นี่คือใน main ของฉัน และใน catch ฉันจะยกเลิกโปรแกรม นอกจากนี้ อาร์กิวเมนต์ยังเป็นไฟล์ที่จะเปิด ดังนั้นจึงไม่มีอินพุตที่ปลอดภัยที่รู้จักซึ่งจะไม่ทำให้เกิดข้อยกเว้น


person Anders    schedule 10.09.2015    source แหล่งที่มา
comment
ใส่รหัสที่เกี่ยวข้องทั้งหมดลงในบล็อก try หรือในฟังก์ชันที่คุณเรียกใช้ในบล็อคลอง   -  person juanchopanza    schedule 10.09.2015
comment
ด้วยโค้ดที่เกี่ยวข้อง คุณหมายถึงโค้ดที่ใช้อ็อบเจ็กต์ใช่หรือไม่ นั่นจะหมายถึงโปรแกรมส่วนใหญ่ของฉัน ดูเหมือนว่าจะมากไปสักหน่อยในการตรวจจับข้อผิดพลาดที่อาจเกิดขึ้นระหว่างการเริ่มต้นเท่านั้น   -  person Anders    schedule 10.09.2015
comment
เป็นเรื่องปกติที่โปรแกรมส่วนใหญ่ของคุณจะอยู่ในฟังก์ชัน main() ใช่ไหม? แล้วทำไมไม่เก็บมันไว้ในฟังก์ชันอื่นที่คุณใส่ไว้ในบล็อคลองล่ะ?   -  person juanchopanza    schedule 10.09.2015
comment
หากโปรแกรมทั้งหมดของคุณอาศัยอ็อบเจ็กต์ bar และไม่สามารถสร้างได้ แสดงว่าคุณมีปัญหาเล็กน้อย   -  person MSalters    schedule 10.09.2015
comment
@MSalters ใช่ฉันทำ ในกรณีนี้ผมจะยกเลิกโปรแกรม ขออภัยที่ไม่ชัดเจนเกี่ยวกับเรื่องนั้น   -  person Anders    schedule 10.09.2015


คำตอบ (2)


ปัญหาค่อนข้างง่าย: ตัวสร้างล้มเหลว ดังนั้นจึงไม่เคยสร้างอ็อบเจ็กต์ bar C++ บังคับใช้สิ่งนี้ และป้องกันไม่ให้คุณใช้ bar ในกรณีนั้น

คุณสามารถแก้ไขปัญหานี้ด้วยวิธีอื่น:

foo makeFoo()
{
   try {
     return foo("Hello!"); // May throw
   }
   catch(...) {
     return foo("Safe"); // We know that "Safe" will not throw.
   }
}

bar foo{makeFoo()};

หากคุณต้องการออกจากโปรแกรมหากมีข้อยกเว้นเกิดขึ้น คุณสามารถพิมพ์ข้อความแสดงข้อผิดพลาดและเรียก exit(EXIT_FAILURE) ภายใน catch

person MSalters    schedule 10.09.2015
comment
ขอบคุณสำหรับคำตอบ! ฉันเกรงว่าไม่มีอินพุตที่รู้จักที่ปลอดภัยอย่างสมบูรณ์ เนื่องจากพารามิเตอร์เป็นไฟล์ที่ต้องอ่าน และฉันคิดว่าไม่มี null หรืออะไรทำนองนั้นใน C ++ ที่ฉันสามารถส่งคืนได้ - person Anders; 10.09.2015
comment
@Anders: วัตถุไม่สามารถเป็น null พอยน์เตอร์สามารถเป็น nullptr ได้ และมี boost::optional<foo> ซึ่งอาจมีหรือไม่มี foo หากไฟล์สำคัญของคุณหายไป คุณสามารถพิมพ์ข้อความแสดงข้อผิดพลาดและโทร exit(EXIT_FAILURE) เข้าไปข้างในได้ - person MSalters; 10.09.2015
comment
ไม่รู้เกี่ยวกับ exit นั่นช่วยแก้ปัญหาของฉัน ขอบคุณ! - person Anders; 10.09.2015

คุณสามารถใช้การจัดสรรฮีป:

foo *p = 0;
try {
    p = new foo("parm");
} catch(const Error& err) {
    ...
}
foo& instance = *p;
// Here you can use instance normally...

delete p; // destroy before leaving scope (or use a smart pointer)
person 6502    schedule 10.09.2015
comment
สิ่งนี้ทำให้คุณได้รับการอ้างอิงแบบโมฆะ นอกจากนี้ ทำไมไม่ std::unique_ptr? - person MSalters; 10.09.2015
comment
@MSalters: ฉันคิดว่าภายใน catch เนื้อความเขาจะแก้ปัญหาไม่ว่าจะจัดสรรวัตถุที่ใช้งานได้หรือเพียงแค่ยกเลิกโปรแกรมและไม่ออกนอกขอบเขตโดยไม่มีวัตถุที่ใช้งานได้ การใช้หรือใช้ตัวชี้อัจฉริยะคือสิ่งที่ฉันคิดจริงๆ... - person 6502; 10.09.2015
comment
นี่คือใน main ของฉัน และใน catch ฉันจะพิมพ์ข้อความแสดงข้อผิดพลาดและ return - person Anders; 10.09.2015