Pada dasarnya itulah pertanyaannya, apakah ada cara yang "benar" untuk menerapkan operator<<
? Membaca ini saya dapat melihat bahwa sesuatu seperti:
friend bool operator<<(obj const& lhs, obj const& rhs);
lebih disukai daripada sesuatu seperti
ostream& operator<<(obj const& rhs);
Tapi saya tidak bisa mengerti mengapa saya harus menggunakan salah satu.
Kasus pribadi saya adalah:
friend ostream & operator<<(ostream &os, const Paragraph& p) {
return os << p.to_str();
}
Tapi saya mungkin bisa melakukan:
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Apa alasan saya harus mendasarkan keputusan ini?
Catatan :
Paragraph::to_str = (return paragraph)
dimana paragraf adalah string.
c++
operator-overloading
Federico Builes
sumber
sumber
Jawaban:
Masalahnya di sini adalah interpretasi Anda terhadap artikel yang Anda tautkan .
Persamaan
Artikel ini tentang seseorang yang mengalami masalah dalam mendefinisikan operator hubungan bool dengan benar.
Operator:
Operator ini harus mengembalikan bool karena mereka membandingkan dua objek dengan tipe yang sama. Biasanya paling mudah untuk mendefinisikan operator ini sebagai bagian dari kelas. Ini karena sebuah kelas secara otomatis menjadi teman dari dirinya sendiri sehingga objek berjenis Paragraph dapat saling memeriksa (bahkan satu sama lain anggota pribadi).
Ada argumen untuk membuat fungsi berdiri bebas ini karena ini memungkinkan konversi otomatis mengonversi kedua sisi jika mereka bukan jenis yang sama, sementara fungsi anggota hanya memungkinkan rhs dikonversi otomatis. Saya menemukan ini argumen pria kertas karena Anda tidak benar-benar ingin konversi otomatis terjadi di tempat pertama (biasanya). Tetapi jika ini adalah sesuatu yang Anda inginkan (saya tidak merekomendasikannya) maka membuat komparator berdiri bebas bisa menguntungkan.
Streaming
Operator aliran:
Jika Anda menggunakan ini sebagai operator aliran (bukan pergeseran biner), parameter pertama adalah aliran. Karena Anda tidak memiliki akses ke objek aliran (bukan milik Anda untuk dimodifikasi) ini tidak dapat menjadi operator anggota, mereka harus berada di luar kelas. Oleh karena itu, mereka harus menjadi teman sekelas atau memiliki akses ke metode publik yang akan melakukan streaming untuk Anda.
Ini juga tradisional untuk objek ini untuk mengembalikan referensi ke objek aliran sehingga Anda bisa merantai operasi aliran bersama-sama.
sumber
operator<<
private:
?freiend
adalah cara untuk memperluas antarmuka publik tanpa merusak enkapsulasi. Baca programmers.stackexchange.com/a/99595/12917Anda tidak dapat melakukannya sebagai fungsi anggota, karena
this
parameter implisit adalah sisi kiri<<
-operator. (Oleh karena itu, Anda perlu menambahkannya sebagai fungsi anggota keostream
-kelas. Tidak bagus :)Bisakah Anda melakukannya sebagai fungsi gratis tanpa
friend
itu? Itulah yang saya suka, karena menjelaskan bahwa ini adalah integrasi denganostream
, dan bukan fungsionalitas inti kelas Anda.sumber
friend
fungsi memiliki hak yang sama sebagai fungsi anggota ( ini adalah apafriend
artinya), sehingga pengguna kelas, saya harus bertanya-tanya mengapa hal itu akan membutuhkan. Ini adalah perbedaan yang saya coba buat dengan kata-kata "fungsionalitas inti".Jika memungkinkan, sebagai fungsi non-anggota dan non-teman.
Seperti yang dijelaskan oleh Herb Sutter dan Scott Meyers, lebih memilih fungsi non-teman bukan anggota daripada fungsi anggota, untuk membantu meningkatkan enkapsulasi.
Dalam beberapa kasus, seperti streaming C ++, Anda tidak memiliki pilihan dan harus menggunakan fungsi non-anggota.
Namun tetap saja, itu tidak berarti Anda harus menjadikan fungsi-fungsi ini sebagai teman kelas Anda: Fungsi-fungsi ini masih dapat mengakses kelas Anda melalui pengakses kelas Anda. Jika Anda berhasil menyusun fungsi tersebut dengan cara ini, maka Anda menang.
Tentang prototipe operator << dan >>
Saya yakin contoh yang Anda berikan dalam pertanyaan Anda salah. Sebagai contoh;
Saya bahkan tidak bisa mulai memikirkan bagaimana metode ini bisa bekerja dalam aliran.
Berikut adalah dua cara untuk mengimplementasikan operator << dan >>.
Katakanlah Anda ingin menggunakan objek seperti aliran tipe T.
Dan Anda ingin mengekstrak / menyisipkan dari / ke dalam T data yang relevan dari objek Anda berjenis Paragraph.
Operator generik << dan >> prototipe fungsi
Yang pertama sebagai fungsi:
Prototipe metode << dan >> operator generik
Yang kedua sebagai metode:
Perhatikan bahwa untuk menggunakan notasi ini, Anda harus memperluas deklarasi kelas T. Untuk objek STL, ini tidak dimungkinkan (Anda tidak seharusnya memodifikasinya ...).
Dan bagaimana jika T adalah aliran C ++?
Berikut adalah prototipe dari operator << dan >> yang sama untuk aliran C ++.
Untuk basic_istream dan basic_ostream generik
Perhatikan bahwa ini adalah kasus streaming, karena Anda tidak dapat mengubah aliran C ++, Anda harus mengimplementasikan fungsinya. Artinya seperti:
Untuk char istream dan ostream
Kode berikut hanya akan berfungsi untuk aliran berbasis karakter.
Rhys Ulerich berkomentar tentang fakta bahwa kode berbasis char hanyalah "spesialisasi" dari kode generik di atasnya. Tentu saja, Rhys benar: Saya tidak merekomendasikan penggunaan contoh berbasis karakter. Ini hanya diberikan di sini karena lebih mudah dibaca. Karena ini hanya dapat dijalankan jika Anda hanya bekerja dengan aliran berbasis char, Anda harus menghindarinya pada platform di mana kode wchar_t umum (misalnya pada Windows).
Semoga ini bisa membantu.
sumber
Ini harus diimplementasikan sebagai fungsi non-teman gratis, terutama jika, seperti kebanyakan hal hari ini, keluarannya terutama digunakan untuk diagnostik dan logging. Tambahkan pengakses const untuk semua hal yang perlu dimasukkan ke dalam keluaran, lalu minta keluaran tersebut untuk memanggilnya dan melakukan pemformatan.
Saya sebenarnya telah mengumpulkan semua fungsi gratis keluaran ostream ini di header "ostreamhelpers" dan file implementasi, itu membuat fungsi sekunder itu jauh dari tujuan sebenarnya dari kelas.
sumber
Tanda tangannya:
Tampaknya agak mencurigakan, ini tidak sesuai dengan
stream
konvensi atau konvensi bitwise sehingga terlihat seperti kasus penyalahgunaan kelebihan beban operator,operator <
harus kembalibool
tetapioperator <<
mungkin harus mengembalikan sesuatu yang lain.Jika Anda bermaksud begitu, katakan:
Kemudian karena Anda tidak dapat menambahkan fungsi
ostream
dengan kebutuhan, fungsi tersebut harus merupakan fungsi gratis, apakah itufriend
tergantung atau tidak pada apa yang harus diakses (jika tidak perlu mengakses anggota pribadi atau dilindungi, tidak perlu membuatnya. teman).sumber
ostream
akan diperlukan saat menggunakanostream.operator<<(obj&)
pemesanan; karenanya fungsi bebas. Jika tidak, tipe pengguna perlu tipe uap untuk mengakomodasi akses.Demi penyelesaian, saya ingin menambahkan bahwa Anda memang dapat membuat operator
ostream& operator << (ostream& os)
di dalam kelas dan dapat berfungsi. Dari apa yang saya tahu, bukan ide yang baik untuk menggunakannya, karena sangat berbelit-belit dan tidak intuitif.Mari kita asumsikan kita memiliki kode ini:
Jadi untuk menyimpulkannya - Anda bisa melakukannya, tetapi kemungkinan besar Anda tidak boleh :)
sumber
operator teman = hak yang sama sebagai kelas
sumber
operator<<
diimplementasikan sebagai fungsi teman:Ini bisa menjadi fungsi teman hanya karena objek ada di sisi kanan
operator<<
dan argumencout
di sisi kiri. Jadi ini tidak bisa menjadi fungsi anggota kelas, itu hanya bisa menjadi fungsi teman.sumber