C ++ 11 neden " delete
d" işlevlerinin aşırı yük çözümlemesine katılmasını sağlar ?
Bu neden yararlıdır? Ya da başka bir deyişle, tamamen silinmek yerine neden gizleniyorlar?
C ++ 11 neden " delete
d" işlevlerinin aşırı yük çözümlemesine katılmasını sağlar ?
Bu neden yararlıdır? Ya da başka bir deyişle, tamamen silinmek yerine neden gizleniyorlar?
Yanıtlar:
= delete
Sözdiziminin amacının yarısı, insanların belirli parametreleri belirli parametrelerle çağırmasını engelleyebilmektir. Bu, esas olarak belirli belirli senaryolarda örtük dönüştürmeleri önlemek içindir. Belirli bir aşırı yüklemeyi yasaklamak için, aşırı yük çözümlemesine katılması gerekir.
Verdiğiniz cevap size mükemmel bir örnek verir:
struct onlydouble {
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
Eğer delete
fonksiyon tamamen kaldırılır, o yapacak = delete
Buna sözdizimi eşdeğer:
struct onlydouble2 {
onlydouble2(double);
};
Bunu yapabilirsin:
onlydouble2 val(20);
Bu yasal C ++ 'dır. Derleyici tüm kuruculara bakacaktır; hiçbiri doğrudan bir tamsayı türü almaz. Ama içlerinden biri örtük bir din değiştirmeden sonra bunu alabilir. Yani buna diyecek.
onlydouble val(20);
Bu yasal C ++ değildir . Derleyici, delete
d olanlar dahil tüm kuruculara bakacaktır . Tam bir eşleşme std::intmax_t
görecektir (herhangi bir tamsayı ile tam olarak eşleşecektir). Bu yüzden derleyici onu seçecek ve hemen bir hata verecektir, çünkü bir delete
d fonksiyonu seçmiştir .
= delete
"Bunu yasaklıyorum" demek sadece "Bu yok" demek değil. Bu çok daha güçlü bir ifade.
C ++ standardının neden "bu mevcut değil" yerine = sil "bunu yasaklıyorum" anlamına geldiğini soruyordum.
Çünkü "bu yok" demek için özel bir gramere ihtiyacımız yok. Bunu örtük olarak, söz konusu belirli "bunu" ilan etmeyerek elde ederiz. "Bunu yasaklıyorum" , özel dilbilgisi olmadan elde edilemeyen bir yapıyı temsil eder . Bu yüzden "bunu yasaklıyorum" demek için özel bir gramer alırız, diğerini değil.
Açık bir "bu yok" dilbilgisine sahip olarak kazanacağınız tek işlevsellik, birisinin daha sonra var olduğunu bildirmesini engellemek olacaktır. Ve bu kendi dilbilgisine ihtiyaç duyacak kadar kullanışlı değil.
Kopya oluşturucunun olmadığını beyan etmenin başka bir yolu yoktur ve varlığı anlamsız belirsizliklere neden olabilir.
Kopya yapıcısı özel bir üye işlevidir. Her sınıfın her zaman bir kopya oluşturucusu vardır. Her zaman bir kopya atama operatörüne, taşıma yapıcısına vb. Sahip oldukları gibi.
Bu işlevler mevcuttur; soru sadece onları çağırmanın yasal olup olmadığıdır. = delete
Bunun var olmadıkları anlamına geldiğini söylemeye çalışırsanız , o zaman belirtimin bir işlevin var olmamasının ne anlama geldiğini açıklaması gerekir. Bu, spesifikasyonun ele aldığı bir kavram değildir.
Henüz bildirilmemiş / tanımlanmamış bir işlevi çağırmaya çalışırsanız, derleyici hata verecektir. Ancak tanımlanmamış bir tanımlayıcı nedeniyle hata verecektir , "işlev yok" hatası nedeniyle değil (derleyiciniz bunu bu şekilde bildirse bile). Çeşitli kurucuların tümü aşırı yük çözümü ile adlandırılır, bu nedenle "varoluşları" bu bağlamda ele alınır.
Her durumda, ya tanımlayıcı aracılığıyla bildirilen bir işlev ya da bir kurucu / yıkıcı vardır (aynı zamanda tanımlayıcı yoluyla da bildirilir, sadece bir tür tanımlayıcı). Operatör aşırı yükleme, tanımlayıcıyı sözdizimsel şekerin arkasına gizler, ancak yine de oradadır.
C ++ belirtimi, "var olmayan bir işlev" kavramını işleyemez. Bir aşırı yük uyumsuzluğunun üstesinden gelebilir. Aşırı yük belirsizliğini kaldırabilir. Ama orada ne olmadığını bilmiyor. Bu yüzden = delete
, daha az yararlı olan "bu satırı hiç yazmamışmışım gibi davranmak" yerine çok daha yararlı olan "bu başarısızlığı çağırma girişimleri" açısından tanımlanır.
Ve yine ilk bölümü yeniden okuyun. Sen bunu yapamaz ile "fonksiyonu yok." Bu şekilde tanımlanmasının başka bir nedeni de budur: çünkü = delete
sözdiziminin ana kullanım durumlarından biri , kullanıcıyı belirli parametre türlerini kullanmaya, açıkça çevirmeye vb. Zorlayabilmektir. Temel olarak, örtük tür dönüşümlerini engellemek için.
Öneriniz bunu yapmaz.
= delete
istediğim "bu üye yok" demek istemiştim, bu da aşırı yük çözümüne katılamayacağı anlamına gelir.
= delete
"bu üye mevcut değil" demekse , o zaman gönderdiğim ilk örnek, insanların onlydouble
kurucusuna tamsayı geçirmesini engelleyemezdi , çünkü onlydouble
silinen aşırı yük mevcut olmayacaktır . Aşırı yük çözümlemesine katılmaz ve bu nedenle tam sayıları geçmenizi engellemez. = delete
Sözdiziminin amacının yarısı olan : "X'i bu işleve örtük olarak geçiremezsiniz" diyebilmek.
=delete
? Sonuçta, aynı şeyi yaparak "kopyalanamaz" diyebiliriz: kopya yapıcısını / atamayı özel ilan ederek. Ayrıca, bir şeyi özel olarak bildirmenin onu çağrılamaz hale getirmediğini unutmayın; sınıf içindeki kod yine de çağırabilir. Yani aynı değil = delete
. Hayır, = delete
sözdizimi daha önce oldukça uygunsuz ve anlaşılmaz olan bir şeyi çok daha açık ve makul bir şekilde yapmamıza izin veriyor.
C ++ Çalışma Taslağı 2012-11-02 bu kuralın arkasında bir mantık sunmuyor, sadece bazı örnekler
8.4.3 Silinen tanımlar [dcl.fct.def.delete]
...
3 [ Örnek : Varsayılan olmayan başlatma ve integral olmayan başlatma şu şekilde uygulanabilir:
struct onlydouble {
onlydouble() = delete; // OK, but redundant
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
- son örnek ]
[ Örnek : Bir sınıfın belirli yeni ifadelerde kullanılması, o sınıf için yeni kullanıcı tanımlı bir işlecin silinmiş tanımlarını kullanarak önlenebilir.
struct sometype {
void *operator new(std::size_t) = delete;
void *operator new[](std::size_t) = delete;
};
sometype *p = new sometype; // error, deleted class operator new
sometype *q = new sometype[3]; // error, deleted class operator new[]
- son örnek ]
[ Örnek : Kopyalama yapıcısının silinmiş tanımlarını ve kopya atama operatörünü kullanarak ve ardından taşıma yapıcısının ve taşıma atama operatörünün varsayılan tanımlarını sağlayarak bir sınıfı kopyalanamaz, yani yalnızca taşıma yapılabilir.
struct moveonly {
moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default;
~moveonly() = default;
};
moveonly *p;
moveonly q(*p); // error, deleted copy constructor
- son örnek ]