Mengapa fungsi virtual murni diinisialisasi oleh 0?

147

Kami selalu mendeklarasikan fungsi virtual murni sebagai:

virtual void fun () = 0 ;

Yaitu, selalu ditugaskan ke 0.

Apa yang saya pahami adalah bahwa ini adalah untuk menginisialisasi entri vtable untuk fungsi ini ke NULL dan nilai lainnya di sini menghasilkan kesalahan waktu kompilasi. Apakah pemahaman ini benar atau tidak?

Mukeshkumar
sumber
12
Perhatikan bahwa vtable bukan persyaratan bahasa, tetapi hanya opsi implementasi untuk metode virtual. Kompiler dapat membuat abstraksi yang sama dengan implementasi yang berbeda (yaitu, tanpa vtable, dan tanpa elemen apa pun menjadi 0)
David Rodríguez - dribeas
@ ketik Re pertanyaan tambahan Anda - itulah yang jawaban saya (dan beberapa orang lain) katakan.
Hanya ingin tahu, apa yang terjadi jika saya memberi, virtual void func() = 100;
krithikaGopalakrisnan

Jawaban:

161

Alasan =0yang digunakan adalah bahwa Bjarne Stroustrup tidak berpikir dia bisa mendapatkan kata kunci lain, seperti "murni" melewati komunitas C ++ pada saat fitur tersebut sedang dilaksanakan. Ini dijelaskan dalam bukunya, The Design & Evolution of C ++ , bagian 13.2.3:

Sintaks penasaran = 0 dipilih ... karena pada saat itu saya tidak melihat peluang untuk mendapatkan kata kunci baru yang diterima.

Dia juga menyatakan secara eksplisit bahwa ini tidak perlu mengatur entri vtable ke NULL, dan melakukannya bukan cara terbaik untuk mengimplementasikan fungsi virtual murni.


sumber
4
Yap, itu hanya sintaks. Saya telah melihat banyak proyek yang #define PURE = 0 dan mereka akan mengatakan virtual void Foo () PURE;
i_am_jorf
79
Tolong Tuhan jauhkan aku dari proyek-proyek itu :-)
27
Jauh lebih buruk daripada #define BEGIN {#define END} ;-) dan saya sering melihatnya.
Toon Krijthe
5
Jenis bagus ini membuat saya berpikir C ++ tidak terlalu halus. Ini aneh mengingat sudah banyak digunakan. Saya berharap bahasanya akan lebih baik dengan berlalunya hari.
jokoon
19
Jadi, dengan kata lain, Bjarne "dihadapkan dengan tenggat waktu" dan "menggunakan peretasan" untuk melewati "cacat desain";) (Cuma bercanda)
Carl
78

Seperti kebanyakan pertanyaan "Mengapa" tentang desain C ++, tempat pertama untuk melihat adalah Desain dan Evolusi C ++ , oleh Bjarne Stroustrup 1 :

=0Sintaks yang aneh dipilih daripada alternatif yang jelas untuk memperkenalkan kata kunci baru pureatau abstractkarena pada saat itu saya tidak melihat peluang untuk mendapatkan kata kunci baru yang diterima. Seandainya saya menyarankan pure, Rilis 2.0 akan dikirim tanpa kelas abstrak. Diberi pilihan antara sintaksis yang lebih bagus dan kelas abstrak, saya memilih kelas abstrak. Alih-alih mengambil risiko menunda dan menimbulkan pertikaian tertentu pure, saya menggunakan tradisi C dan C ++ yang menggunakan konvensi 0 untuk menyatakan "tidak ada." The =0sintaks cocok dengan pandangan saya bahwa fungsi tubuh adalah initializer untuk fungsi juga dengan (sederhana, tetapi biasanya memadai) pandangan dari himpunan fungsi virtual diimplementasikan sebagai vektor fungsi pointer. [...]

1 §13.2.3 Sintaks

Jerry Coffin
sumber
29

Bagian 9.2 dari standar C ++ memberikan sintaks untuk anggota kelas. Ini termasuk produksi ini:

pure-specifier:
    = 0

Tidak ada yang spesial dari nilai tersebut. "= 0" hanyalah sintaks untuk mengatakan "fungsi ini murni virtual." Ini tidak ada hubungannya dengan inisialisasi atau null pointer atau nilai numerik nol, meskipun kesamaan dengan hal-hal itu mungkin memiliki nilai mnemonik.

Kristopher Johnson
sumber
5
+1 untuk merujuk pada Standar C ++. Agak mengejutkan bahwa salah satu jawaban terbaik dan hanya mendapat 1 suara sejauh ini. Membaca standar harus menjadi langkah pertama untuk menyelesaikan pertanyaan C ++.
mloskot
7
@mloskot: mungkin karena tidak menjawab pertanyaan OP, hanya menyatakan kembali situasinya?
hanya seseorang
6
@ just some - Ini termasuk kutipan standar yang menyatakan apa sintaks deklarasi fungsi virtual murni dan bahwa sintaksis menggunakan pure-specifier = 0Apa lagi yang ingin Anda ketahui? Itu akan sama dengan bertanya mengapa fungsi tubuh dibungkus dengan {} Jawabannya adalah, karena itulah yang mendefinisikan sintaksis C ++.
mloskot
19

Saya tidak yakin apakah ada makna di balik ini. Itu hanya sintaks bahasa.

cquillen
sumber
16

C ++ selalu menghindar dari memperkenalkan kata kunci baru, karena kata-kata baru yang dicadangkan menghancurkan program lama yang menggunakan kata-kata ini untuk pengidentifikasi. Ini sering dilihat sebagai salah satu kekuatan bahasa yang menghormati kode lama sejauh mungkin.

The = 0sintaks memang mungkin telah dipilih karena menyerupai pengaturan entri vtable untuk 0, tapi ini adalah murni simbolis. (Sebagian besar kompiler menetapkan entri vtable tersebut ke sebuah rintisan yang memancarkan kesalahan sebelum membatalkan program.) Sintaksinya terutama dipilih karena tidak digunakan untuk apa pun sebelumnya dan itu menyelamatkan memperkenalkan kata kunci baru.

sbi
sumber
3
+1 untuk menjelaskan kerugian memperkenalkan kata kunci baru. Itu membantu untuk memahami alasannya, tetapi sintaksis C ++ tampaknya berbelit-belit bagi saya dan saya berharap mereka akan membuatnya lebih mudah dibaca oleh manusia - purekata kunci akan sangat bagus dalam buku saya. Bagaimanapun, ada baiknya memahami alasannya.
Keith Pinson
@KeithPinson Jika Anda ingin kata kunci murni, Anda bisa #define pure = 0.
jdh8
@ jdh8: Ugh. Hanya ... Ugh.
sbi
Sebagai catatan tambahan, di kelas dengan Bjarne dia berkata dia benar-benar ingin mendapatkan kata kunci "murni" ke C ++ ... tapi dia mencoba untuk mendapatkannya di akhir siklus sebelum kompiler C ++ akan dikirim (IIRC kurang dari dua minggu). Seolah-olah, itu tidak berhasil masuk.
ThePhD
@ThePhD: ISTR dia juga mengatakan ini di suatu tempat di D&E. (Tapi aku terlalu malas untuk mencarinya.)
sbi
11

C ++ harus memiliki cara untuk membedakan fungsi virtual murni dari deklarasi fungsi virtual normal. Mereka memilih untuk menggunakan = 0sintaks. Mereka bisa saja dengan mudah melakukan hal yang sama dengan menambahkan kata kunci murni. Tetapi C ++ cukup enggan untuk menambahkan kata kunci baru dan lebih suka menggunakan mekanisme lain untuk memperkenalkan fitur.

JaredPar
sumber
2
-0: ketika Anda tidak memiliki sesuatu yang substansial untuk dikatakan sendiri, gunakan kutipan yang luas (lihat jawaban Jerry Coffin untuk +1;)
hanya seseorang
7

Tidak ada "initilaized" atau "ditugaskan" nol dalam kasus ini. = 0hanya dalam konstruksi sintaksis yang terdiri dari =dan 0token, yang sama sekali tidak ada hubungannya dengan inisialisasi atau penugasan.

Ini tidak ada hubungannya dengan nilai aktual di "vtable". Bahasa C ++ tidak memiliki gagasan "vtable" atau apapun seperti itu. Berbagai "vtables" tidak lebih dari sekadar detail implementasi spesifik.

Semut
sumber
3

Saya ingat membaca bahwa pembenaran untuk sintaks lucu adalah bahwa itu lebih mudah (dalam hal standar-penerimaan) daripada memperkenalkan kata kunci lain yang akan melakukan hal yang sama.

Saya percaya ini disebutkan dalam Desain dan Evolusi C ++ oleh Bjarne Stroustrup.

Lukas
sumber
2

Saya akan berasumsi bahwa ini hanya bagian dari tata bahasa C ++. Saya tidak berpikir ada batasan bagaimana kompiler benar-benar mengimplementasikan ini untuk format biner tertentu. Anda anggap mungkin tepat untuk kompiler C ++ awal.

rui
sumber
2

The = 0mendeklarasikan fungsi virtual murni .

Apa yang dipahami adalah bahwa ini adalah untuk menginisialisasi entri vtable untuk fungsi ini ke NULL dan nilai lainnya di sini menghasilkan kesalahan waktu kompilasi

Saya pikir itu tidak benar. Itu hanya sintaks khusus. Vtable ditentukan oleh implementasi. Tidak ada yang mengatakan entri vtable untuk anggota murni harus benar-benar nol pada konstruksi (meskipun sebagian besar kompiler menangani vtable serupa).

Alexander Gessler
sumber
4
Itu sebenarnya tidak benar. Tidak ada yang salah dengan memberikan definisi untuk fungsi virtual murni. Satu-satunya hal yang = 0dilakukan adalah membuat seluruh kelas abstrak dan melarang panggilan virtual ke fungsi murni. Panggilan non-virtual masih sangat baik, yaitu ketika definisi (jika Anda memberikan satu) digunakan.
AnT
Lihat saja keluaran godbolt. Tidak ada ruang untuk ambiguitas atau spekulasi. Saya akan memeriksanya sendiri nanti
Lewis Kelsey
Tampaknya itu menggantikan entri dengan __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… bukannya Base :: f ()
Lewis Kelsey
1

Nah, Anda juga dapat menginisialisasi entri vtable untuk menunjuk ke fungsi sebenarnya "

 virtual void fun()
 {
     //dostuff()
 }

Tampaknya intuitif bahwa entri vtable dapat didefinisikan untuk menunjuk ke mana saja (0) atau ke suatu fungsi. Membiarkan Anda menentukan nilai Anda sendiri untuk itu mungkin akan menghasilkan menunjuk ke sampah, bukan ke suatu fungsi. Tapi itu sebabnya "= 0" diizinkan dan "= 1" tidak. Saya menduga Neil Butterworth benar tentang mengapa "= 0" digunakan sama sekali

Brian
sumber
1
Walaupun saya memiliki pendapat yang serupa tetapi karena banyak yang mengutip standar dan komentar Bjarne tentang hal yang sama, kami memiliki peluang minimal untuk berargumen :)
mukeshkumar