Saf sanal işlev neden 0 ile başlatılır?


147

Her zaman saf bir sanal işlev beyan ederiz:

virtual void fun () = 0 ;

Yani, her zaman 0'a atanır.

Ne anlamak bu NULL için bu işlev için vtable giriş başlatmak olduğunu ve burada başka bir değer derleme zamanı hatası ile sonuçlanır olduğunu. Bu anlayış doğru mu değil mi?


12
Vtable'ın bir dil gereksinimi değil, yalnızca sanal yöntemler için bir uygulama seçeneği olduğunu unutmayın. Bir derleyici farklı bir uygulama ile aynı soyutlamayı yaratabilir (yani, vtable olmadan ve herhangi bir eleman olmadan 0 olur)
David Rodríguez - dribeas

@hype Tamamlayıcı sorunuz yeniden - yanıtım (ve diğerleri).

Sadece merak ediyorum, ne verirsen ne olur, virtual void func() = 100;
krithikaGopalakrisnan

Yanıtlar:


161

Bunun nedeni =0, Bjarne Stroustrup'un, özelliğin uygulandığı sırada C ++ topluluğunu geçerek "saf" gibi başka bir anahtar kelime alabileceğini düşünmemesidir. Bu, C ++ Tasarım ve Evrimi , bölüm 13.2.3:

Meraklı = 0 sözdizimi seçildi ... çünkü o zaman yeni bir anahtar kelimenin kabul edilme şansını görmedim.

Ayrıca, bunun vtable girdisini NULL olarak ayarlaması gerekmediğini ve bunu yapmanın saf sanal işlevleri uygulamanın en iyi yolu olmadığını açıkça belirtir.


4
Evet, sadece sözdizimi. #Define PURE = 0 olan bir sürü proje gördüm ve sanal voo Foo () PURE derler;
i_am_jorf

79
Lütfen Tanrım beni bu projelerden uzak tut :-)

27
#Define BEGIN {#define END} ;-) çok daha az kötü ve bazen bunu gördüm.
Toon Krijthe

5
Bu tür şık şey C ++ 'ın çok cilalı olmadığını düşündürüyor. Çok kullanıldığını düşünmek garip. Umarım geçen günlerde dil daha iyi olur.
jokoon

19
Yani, başka bir deyişle, Bjarne'ni "tasarım hatası" geçmiş olsun "yazarlardan kullanılan" ve "bir süre ile karşı karşıya" olduğunu;) (Sadece) esprili
Carl

78

C ++ tasarımı ile ilgili çoğu "Neden" sorusunda olduğu gibi, bakılacak ilk yer , Bjarne Stroustrup 1'in C ++ Tasarımı ve Evrimi :

Meraklı =0sözdizimi, yeni bir anahtar kelime eklemenin bariz alternatifi üzerinden seçildi pureveya abstracto sırada yeni bir anahtar kelimenin kabul edilmesini hiç şansım olmadı. Eğer önerirsem pure, Sürüm 2.0 soyut sınıflar olmadan gönderilirdi. Güzel bir sözdizimi ve soyut sınıflar arasında bir seçim yapıldığında, soyut sınıfları seçtim. Gecikmeyi riske atmak ve belirli kavgalara maruz kalmak yerine pure, "orada değil" i temsil etmek için 0 kullanma geleneği C ve C ++ geleneğini kullandım. =0Bir fonksiyon vücut işlev işaretçileri vektörü olarak uygulanmakta olan sanal fonksiyonların kümesi (basit, ama genelde yeterli) görünümü ile de bir işlev için başlatıcı olduğunu benim görüntüsü sözdizimi uyuyor. [...]

1 §13.2.3 Sözdizimi


29

C ++ standardının 9.2 bölümü, sınıf üyeleri için sözdizimini verir. Bu üretimi içerir:

pure-specifier:
    = 0

Değer hakkında özel bir şey yok. "= 0" sadece "bu işlev tamamen sanaldır" demenin sözdizimidir. Başlatma veya null işaretçiler veya sıfır sayısal değeri ile ilgisi yoktur, ancak bu şeylere benzerlik anımsatıcı bir değere sahip olabilir.


5
C ++ Standardına başvurmak için +1. Mümkün olan en iyi cevaplardan birinin olması ve şimdiye kadar sadece 1 oy alması şaşırtıcı. Standardı okumak, C ++ sorularını çözmek için ilk adım olmalıdır.
Ocak'ta mloskot

7
@mloskot: belki OP'nin sorusuna cevap vermediği için sadece durumu yeniden ifade ediyor?
sadece birileri

6
@just somebody - Saf sanal işlev bildiriminin sözdiziminin ne olduğunu ve sözdiziminin saf belirtici kullandığını belirten standart alıntıyı içerir. = 0Başka ne bilmek istersiniz? İşlev gövdesinin neden {} ile sarıldığını sormakla aynı olurdu. Cevap C ++ sözdiziminin tanımladığı şeydir.
mloskot

19

Bunun arkasında bir anlam olup olmadığından emin değilim. Bu sadece dilin sözdizimidir.


16

Yeni ayrılmış kelimeler tanımlayıcılar için bu kelimeleri kullanan eski programları bozduğundan, C ++ her zaman yeni anahtar kelimeler sunmaktan kaçınmıştır. Genellikle dilin güçlü yönlerinden biri olarak görülür ve eski koda mümkün olduğunca saygı duyar.

= 0O bir vtable giriş ayarı benzer beri sözdizimi gerçekten seçilmiş olabilir 0, ama bu sadece semboliktir. (Çoğu derleyici, programı iptal etmeden önce bir hata yayan bir saplamaya bu tür vtable girişleri atar.) Sözdizimi esas olarak daha önce hiçbir şey için kullanılmadığı için seçildi ve yeni bir anahtar kelime eklemeyi kaydetti.


3
+1, yeni bir anahtar kelime eklemenin dezavantajını açıklamak için. Bu mantığı anlamak için yararlıdır, ancak C ++ sözdizimi bana saçma geliyor ve keşke daha insan tarafından okunabilir hale getirmelerini isterdim - bir pureanahtar kelime kitabımda harika olurdu. Her neyse, mantığı anlamak güzel.
Keith Pinson

@ KeithPinson Saf bir anahtar kelime istiyorsanız, bunu yapabilirsiniz #define pure = 0.
jdh8

@ jdh8: Ah. Sadece ... Ah.
sbi

Bir yan not olarak, Bjarne ile bir sınıfta gerçekten "saf" anahtar kelimeyi C ++ içine almak istediğini söyledi ... ama C ++ derleyicisinin gönderilmesinden önce onu çok geç saatlerde almaya çalıştı (IIRC) iki haftadan az). Görünürde, başaramadı.
ThePhD

@ThePhD: ISTR da bunu D&E'de bir yerde söylüyor. (Yine de bakmak için çok tembelim.)
sbi

11

C ++, saf bir sanal işlevi, normal bir sanal işlevin bildiriminden ayırmanın bir yoluna sahip olmalıdır. = 0Sözdizimini kullanmayı seçtiler . Saf bir anahtar kelime ekleyerek aynı şeyi kolayca yapabilirlerdi. Ancak C ++ yeni anahtar kelimeler eklemek için oldukça nefret ediyor ve özellikleri tanıtmak için diğer mekanizmaları kullanmayı tercih ediyor.


2
-0: Kendi başınıza söyleyecek önemli bir şeyiniz yoksa, kapsamlı bir alıntı kullanın (Jerry Coffin'in +1 için cevabına bakın;)
sadece birileri

7

Bu durumda hiçbir şey "başlatılmaz" veya "atanmaz". = 0sadece başlatma veya atama ile hiçbir ilgisi olmayan =ve 0belirteçlerden oluşan sözdizimsel bir yapıda .

"Vtable" daki gerçek değerle hiçbir ilişkisi yoktur. C ++ dilinin "vtable" ya da bunun gibi herhangi bir fikri yoktur. Çeşitli "vtables" sadece belirli uygulamaların ayrıntılarından başka bir şey değildir.


3

Komik sözdiziminin gerekçesinin, aynı şeyi yapacak başka bir anahtar kelime tanıtmaktan daha kolay (standartlar kabulü açısından) olduğunu okuduğumu hatırlıyorum.

Bunun Bjarne Stroustrup tarafından C ++ Tasarımı ve Evrimi'nde bahsedildiğine inanıyorum.


2

Bunun sadece C ++ dilbilgisinin bir parçası olduğunu varsayabilirim. Derleyicilerin bunu belirli bir ikili format için nasıl uyguladığına dair herhangi bir kısıtlama olduğunu düşünmüyorum. Muhtemelen erken C ++ derleyicileri için doğru olduğunu varsayıyorsunuz.


2

= 0Bir beyan saf sanal fonksiyon .

Anlaşılan, bunun bu işlevin vtable girişini NULL olarak başlatmak ve buradaki diğer değerlerin derleme zamanı hatasına neden olmasıdır.

Bunun doğru olduğunu düşünmüyorum. Sadece özel bir sözdizimi. Vtable, uygulama tanımlıdır. Hiç kimse, saf bir üye için seçilebilir bir girişin inşaat sırasında aslında sıfırlanması gerektiğini söylemez (çoğu derleyici benzerleri ele alsa da).


4
Aslında bu doğru değil. Saf bir sanal işlev için tanım sağlamada yanlış bir şey yoktur . Tek şey = 0, tüm sınıfı soyutlaştırmak ve saf işlevlere sanal çağrıları yasaklamaktır . Sanal olmayan çağrılar hala kusursuzdur, yani tanım (verdiyseniz) kullanılır.
AnT

Sadece godbolt çıkışına bakın. Belirsizlik veya spekülasyon için yer yoktur. Daha sonra kendime bakacağım
Lewis Kelsey

Giriş yerine Base :: f () yerine __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… ile yer değiştiriyor gibi görünüyor
Lewis Kelsey

1

Ayrıca, vtable girişini gerçek bir işleve işaret edecek şekilde başlatabilirsiniz "

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

Vtable girdisinin hiçbir yere (0) veya bir işleve işaret etmeyecek şekilde tanımlanabileceği sezgisel görünüyor. Bunun için kendi değerinizi belirlemenize izin vermek, muhtemelen bir işlev yerine çöp işaretine neden olur. Ama bu yüzden "= 0" a izin verilir ve "= 1" buna izin verilmez. Neil Butterworth'un "= 0" ın neden kullanıldığına dair haklı olduğunu düşünüyorum


1
Ben bile benzer görüş vardı ama birçok standart alıntı ve Bjarne aynı yorumları alıntı beri, biz argüman minimal şansı var :)
mukeshkumar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.