'Geçersiz kıl' anahtar kelimesi yalnızca geçersiz kılınmış bir sanal yöntem için bir kontrol mü?


227

Anladığım kadarıyla override, C ++ 11'de anahtar kelimenin tanıtımı, uygulanan işlevin temel sınıfta overridebir virtualişlev olduğundan emin olmak için bir denetimden başka bir şey değildir .

Öyle mi?



13
Yine de bir çift kontrol değil. Tek kontrol bu.
Nikos C.14

13
hey, geçersiz kılma bir anahtar kelime DEĞİL, biraz dilbilgisi şekeri. int geçersiz kılma = 42; // Tamam
KAlO2

2
Ayrıca, bildirilen işlevin geçersiz kılındığını açıklayan okunabilirliği geliştirir;)
mots_g

5
Peki, uh ... C ++ 11 ne zaman yerel 4 yılımda böyle şeyler öğretmeye başlayacak kadar standart olacak? Ne zaman öğrenecekler ?!
Cinch

Yanıtlar:


264

Aslında fikir budur. Mesele şu ki, ne demek istediğiniz konusunda açık olursunuz, böylece sessiz bir hata teşhis edilebilir:

struct Base
{
    virtual int foo() const;
};

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

Yukarıdaki kod derlenir, ancak ne demek istediğiniz değil (eksik olduğuna dikkat edin const). Bunun yerine, virtual int foo() overridedediyseniz, işlevinizin aslında hiçbir şeyi geçersiz kılmadığı bir derleyici hatası alırsınız.


74
+1: Ne yazık ki, insanlar yeni overrideözelliğin bunu "düzelttiğini" önerdiğinde, ne yazık ki, biraz kırmızı bir ringa balığı ; yazmayı hatırlamanız gerektiği gibi kullanmayı hatırlamanız gerekir const;)
Orbit'te Hafiflik Yarışları

explicitSınıf tanımlarının C ++ 11'e girmediğini fark ettim . Huh.
aschepler

1
@aschepler explicitSınıf tanımlaması ne yapar? Bunu hiç duymadım.
Christian Rau

18
@LightnessRacesinOrbit: Evet, aptalca bir kanıt değil; Bununla birlikte, genel bir kuralı hatırlamak ( overridebunu yapmak istediğinde çılgınca yazmak ), köşe vakalarını hatırlamaktan daha olasıdır, yani farklı prototiplerin işlevlerini kopyalama konusunda genel bir şey yoktur, sadece yerine eksik constveya yazma gibi düzensizlikler vb.charint
legends2k

1
@Light, bu cevabın en hızlı kullanım örneğinden overridebahsediliyor , ki bu anlıktan daha fütüristik. Cevap override, virtualyöntemle devam etmenizi önerir . İleride imzayı yanlışlıkla değiştirdiğinde, yararlılığı devreye
girer

36

Wikipedia teklifi:

Geçersiz kılma özel tanımlayıcısı, derleyicinin bu tam imzayla sanal bir işlev olup olmadığını görmek için temel sınıf (lar) ı kontrol edeceği anlamına gelir. Ve yoksa, derleyici hata verecektir.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

Düzenle (cevabı biraz geliştirmeye çalışıyor):

Bir yöntemi "geçersiz kılma" olarak bildirmek, bu yöntemin temel sınıfta bir (sanal) yöntemi yeniden yazmayı amaçladığı anlamına gelir . Geçersiz kılma yönteminin, yeniden yazmayı amaçladığı yöntemle aynı imzası (en azından giriş parametreleri için) olması gerekir.

Bu neden gerekli? Peki, aşağıdaki iki yaygın hata durumu önlenir:

  1. yeni yöntemde bir tür yanlış yazılır. Derleyici, önceki bir yöntemi yazmak niyetinde olmadığından, yeni bir yöntem olarak sınıfa ekler. Sorun şu ki, eski yöntem hala orada, yeni yöntem aşırı yük olarak ekleniyor. Bu durumda, eski yönteme yönelik tüm çağrılar, davranışta herhangi bir değişiklik olmadan (yeniden yazmanın amacı olurdu) daha önce olduğu gibi çalışacaktır.

  2. biri, üst sınıftaki yöntemi "sanal" olarak bildirmeyi unutur, ancak yine de bir alt sınıfa yeniden yazmaya çalışır. Bu görünüşte kabul edilecek olsa da, davranış tam olarak amaçlandığı gibi olmayacaktır: yöntem sanal değildir, bu nedenle üst sınıfa doğru işaretçilerden erişim yeni (alt sınıf ') yöntemi yerine eski (üst sınıf') yöntemini çağırmayı sona erdirir.

"Geçersiz kılma" eklemek bunu açıkça belirsizleştirir: bu, derleyiciye üç şeyin beklediğini söyler:

  1. üst sınıfta aynı ada sahip bir yöntem var
  2. üst sınıftaki bu yöntem "sanal" olarak tanımlanır (yani, yeniden yazılması amaçlanmıştır)
  3. üst sınıftaki yöntem, alt sınıftaki yöntemle (yeniden yazma yöntemi) aynı (giriş *) imzasına sahiptir

Bunlardan herhangi biri yanlışsa, bir hata sinyali verilir.

* Not: Çıktı parametresi bazen farklı, ancak ilişkili türde olabilir. İlgiliyse kovaryant ve kontravaryant dönüşümler hakkında bilgi edinin.


31

" Geçersiz kılma " seçeneği, isteğe bağlı bir parametre eklemek gibi temel sınıf sanal yöntem imzasını güncelleyen ancak türetilmiş sınıf yöntemi imzasını güncellemeyi unuttuğunda yararlıdır. Bu durumda, baz ve türetilmiş sınıf arasındaki yöntemler artık polimorfik bir ilişki değildir. Geçersiz kılma bildirimi olmadan, bu tür bir hata bulmak zordur.


1
+1. Her ne overridekadar bu tür sorunları keşfetmenin harika bir yolu olsa da , iyi bir birim test kapsamı da yardımcı olmalıdır.
hayal kırıklığına uğradı

1
Bu yüzden bu yeni belirleyici için çok heyecanlıyım. Tek sorun, bu özelliğin temel sınıflardaki değişikliklerden kaynaklanan hataları önlemek için önceden uygulanması gerektiğidir. ;-)
Wolf


2

C ++ 17 standart taslak

C ++ 17 N4659 standart taslağında tüm overrideisabetlerin üzerinden geçtikten sonra , tanımlayıcıya bulabileceğim tek referans :override

5 Sanal işlev virt-specifier geçersiz kılma ile işaretlenmişse ve bir temel sınıfın üye işlevini geçersiz kılmazsa, program kötü biçimlendirilir. [ Misal:

struct B {
  virtual void f(int);
};

struct D : B {
  virtual void f(long) override; // error: wrong signature overriding B::f
  virtual void f(int) override;  // OK
}

- son örnek]

bu yüzden muhtemelen yanlış programları patlatmanın tek etkisi olduğunu düşünüyorum.

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.