Saya cukup baru mengenal C ++ jadi saya cenderung mendesain dengan banyak Java-isme saat saya belajar. Bagaimanapun, di Jawa, jika saya memiliki kelas dengan metode 'pencarian' yang akan mengembalikan objek T
dari Collection< T >
yang cocok dengan parameter tertentu, saya akan mengembalikan objek itu dan jika objek tidak ditemukan dalam koleksi, saya akan kembali null
. Kemudian dalam fungsi panggilan saya, saya hanya akan memeriksaif(tResult != null) { ... }
Di C ++, saya menemukan bahwa saya tidak dapat mengembalikan null
nilai jika objek tidak ada. Saya hanya ingin mengembalikan 'indikator' tipe T yang memberi tahu fungsi pemanggil bahwa tidak ada objek yang ditemukan. Saya tidak ingin memberikan pengecualian karena ini bukanlah keadaan yang luar biasa.
Seperti inilah tampilan kode saya sekarang:
class Node {
Attr& getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return attributes[i];
//if not found
return NULL; // what should this be?
}
private:
vector<Attr> attributes;
}
Bagaimana saya bisa mengubahnya sehingga saya bisa memberikan penanda semacam itu?
sumber
std::find(first, last, value)
kembalilast
jika tidak ada elemen yang cocok.Jawaban:
Di C ++, referensi tidak boleh null. Jika Anda ingin mengembalikan null secara opsional jika tidak ada yang ditemukan, Anda perlu mengembalikan pointer, bukan referensi:
Sebaliknya, jika Anda bersikeras untuk kembali dengan referensi, Anda harus membuat pengecualian jika atribut tidak ditemukan.
(Ngomong-ngomong, saya sedikit khawatir tentang metode Anda menjadi
const
dan mengembalikan non-const
atribut. Untuk alasan filosofis, saya sarankan kembaliconst Attr *
. Jika Anda juga mungkin ingin memodifikasi atribut ini, Anda dapat membebani dengan non-const
metode mengembalikan non-const
atribut juga.)sumber
nullptr
bukanNULL
untuk c ++ 11 sekarang?Ada beberapa kemungkinan jawaban di sini. Anda ingin mengembalikan sesuatu yang mungkin ada. Berikut ini beberapa pilihan, mulai dari yang paling tidak saya sukai hingga paling disukai:
Kembali dengan referensi, dan sinyal tidak dapat ditemukan dengan pengecualian.
Sepertinya tidak menemukan atribut adalah bagian normal dari eksekusi, dan karenanya tidak terlalu luar biasa. Penanganan untuk ini akan berisik. Nilai null tidak dapat dikembalikan karena perilaku tidak ditentukan memiliki referensi null.
Kembali dengan penunjuk
Sangat mudah untuk lupa memeriksa apakah hasil dari getAttribute akan menjadi penunjuk non-NULL, dan merupakan sumber bug yang mudah.
Gunakan Boost.Optional
A boost :: opsional menandakan dengan tepat apa yang terjadi di sini, dan memiliki metode mudah untuk memeriksa apakah atribut seperti itu ditemukan.
Catatan tambahan: std :: optional baru-baru ini terpilih menjadi C ++ 17, jadi ini akan menjadi hal "standar" dalam waktu dekat.
sumber
boost::optional
tidak melibatkan banyak overhead (tidak ada alokasi dinamis), itulah mengapa ini sangat bagus. Menggunakannya dengan nilai polimorfik membutuhkan pembungkusan referensi atau pointer.Anda dapat dengan mudah membuat objek statis yang mewakili pengembalian NULL.
Dan di suatu tempat di file sumber:
sumber
Jika Anda menginginkan
NULL
nilai kembali, Anda perlu menggunakan pointer, bukan referensi.Referensi tidak bisa dengan sendirinya
NULL
.(Catatan untuk poster komentar di masa mendatang: Ya, Anda dapat memiliki alamat referensi menjadi NULL jika Anda benar-benar mencoba).
Lihat jawaban saya di sini untuk daftar perbedaan antara referensi dan petunjuk .
sumber
Seperti yang telah Anda ketahui bahwa Anda tidak dapat melakukannya seperti yang Anda lakukan di Java (atau C #). Berikut adalah saran lain, Anda bisa meneruskan referensi objek sebagai argumen dan mengembalikan nilai bool. Jika hasilnya ditemukan dalam koleksi Anda, Anda dapat menetapkannya ke referensi yang diteruskan dan mengembalikan 'true', jika tidak mengembalikan 'false'. Harap pertimbangkan kode ini.
Fungsi di atas harus menemukan Operator terhadap kunci 'token', jika menemukan yang mengembalikan nilai true dan menetapkan nilai ke parameter Operator & op.
Kode penelepon untuk rutinitas ini terlihat seperti ini
sumber
Alasan mengapa Anda tidak dapat mengembalikan NULL di sini adalah karena Anda telah menyatakan tipe pengembalian Anda sebagai
Attr&
. Trailing&
membuat nilai yang dikembalikan menjadi "referensi", yang pada dasarnya adalah penunjuk yang dijamin bukan untuk menjadi null ke objek yang ada. Jika Anda ingin mengembalikan null, ubahAttr&
keAttr*
.sumber
Anda tidak dapat mengembalikan
NULL
karena tipe kembalian dari fungsi tersebut adalah objekreference
dan bukanpointer
.sumber
Anda bisa mencoba ini:
sumber