Tangkap kesalahan yang dilemparkan oleh konstruktor di C++?

Saya memiliki kelas foo (yang tidak dapat saya modifikasi) hanya dengan satu konstruktor yang mengambil satu argumen seperti ini:

foo bar("Hello!");

Karena konstruktor dapat menimbulkan kesalahan, saya ingin menerapkan penanganan kesalahan. Upaya pertama saya adalah ini:

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

Namun, sekarang foo berada dalam lingkup blok try dan tidak dapat digunakan di tempat lain. Jika saya memahami semuanya dengan benar, saya tidak dapat mendeklarasikan suatu objek tanpa menginisialisasinya, jadi saya dapat mendeklarasikan bar di luar blok try. Jadi apa yang harus saya lakukan untuk menangkap kesalahan yang dilontarkan konstruktor?

EDIT: Untuk memperjelas, ini ada di main saya, dan di catch saya akan membatalkan program. Selain itu, argumennya adalah file yang akan dibuka, jadi tidak ada input aman yang diketahui yang tidak akan pernah memunculkan pengecualian.


person Anders    schedule 10.09.2015    source sumber
comment
Letakkan semua kode yang relevan di blok coba. Atau dalam fungsi yang Anda panggil di blok try.   -  person juanchopanza    schedule 10.09.2015
comment
Dengan kode yang relevan, maksud Anda kode yang menggunakan objek? Itu berarti sebagian besar program saya. Sepertinya terlalu berlebihan hanya untuk menangkap kesalahan yang mungkin hanya terjadi selama inisialisasi?   -  person Anders    schedule 10.09.2015
comment
Ya, tidak apa-apa jika sebagian besar program Anda dimasukkan ke dalam fungsi main(), bukan? Jadi mengapa tidak memasukkannya ke dalam fungsi lain yang Anda masukkan ke dalam blok coba?   -  person juanchopanza    schedule 10.09.2015
comment
Jika seluruh program Anda bergantung pada objek bar dan gagal dibuat, Anda memiliki sedikit masalah.   -  person MSalters    schedule 10.09.2015
comment
@MSalters Ya, saya tahu. Jadi dalam hal ini saya akan membatalkan program tersebut. Maaf karena tidak jelas tentang itu.   -  person Anders    schedule 10.09.2015


Jawaban (2)


Masalahnya cukup sederhana: konstruktor gagal, sehingga objek bar tidak pernah dibuat. C++ menerapkan ini, dan mencegah Anda menggunakan bar dalam kasus tersebut.

Anda dapat menyelesaikannya dengan cara lain:

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

bar foo{makeFoo()};

Jika Anda ingin keluar dari program jika pengecualian dilempar, Anda dapat mencetak pesan kesalahan dan memanggil exit(EXIT_FAILURE) di dalam tangkapan.

person MSalters    schedule 10.09.2015
comment
Terima kasih atas jawabannya! Saya khawatir tidak ada masukan yang diketahui sepenuhnya aman, karena parameternya adalah file yang akan dibaca. Dan saya pikir tidak ada null atau sesuatu seperti itu di C++ yang bisa saya kembalikan? - person Anders; 10.09.2015
comment
@Anders: Objek tidak boleh null. Pointernya bisa nullptr. Dan ada boost::optional<foo> yang mungkin berisi foo atau tidak. Jika file penting Anda hilang, tentu saja Anda dapat mencetak pesan kesalahan dan memanggil exit(EXIT_FAILURE) di dalam tangkapan. - person MSalters; 10.09.2015
comment
Tidak tahu tentang exit. Itu memecahkan masalah saya. Terima kasih! - person Anders; 10.09.2015

Anda dapat menggunakan alokasi heap:

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
Ini memberi Anda dereferensi penunjuk nol. Juga, mengapa tidak std::unique_ptr? - person MSalters; 10.09.2015
comment
@MSalters: Saya berasumsi bahwa di dalam badan catch dia akan menyelesaikan masalah baik dengan mengalokasikan objek yang berfungsi atau hanya membatalkan program dan tidak keluar dari cakupan tanpa objek yang berfungsi. Dengan atau menggunakan penunjuk cerdas adalah apa yang saya pikirkan... - person 6502; 10.09.2015
comment
Ini di main saya, dan di catch saya hanya akan mencetak pesan kesalahan dan return. - person Anders; 10.09.2015