2010-03-05 27 views
6

Aşağıdaki kodu düşünün sanal işlevi geçersiz kılmak için: derlenmiş zamanİstisna şartname


class A 
{ 
public: 
    virtual void f() throw (int) { } 
}; 

class B: public A 
{ 
public: 
    void f() throw (int, double) { } 
}; 

, bu türetilmiş B sınıfı bu önemi nedir A'ya kıyasla daha gevşek bir atış belirtici olduğunu söylüyor? Eğer istisna özelliklerini değiştirmeye çalışırsak, A :: f() B: f() sadece int atarken int ve double atar, hata görünmez.

+2

İçtenlikle, istisna olarak kullanılmak üzere tasarlanmamış sınıfların örneklerini atmadığınızı umuyoruz ve bu sadece sorunuzun hızlı ve kirli bir örneğidir :) –

+0

Matthieu: Ah, evet tabiki. Anlıyorum. – jasonline

cevap

13
  1. Don't use exception specifications in C++. Java'nınkilere kıyasla çok karşı sezgiseldir.
  2. Türetilmiş sınıfta daha geniş bir belirtime sahip olmak LSP (Liskov İkame Prensibi).

noktasında 2 genişletmek için: A 'ın arayanlar sadece int çıkar bekliyoruz ama kullanırsanız bir aniden double (o alenen A türetilen çünkü, aynı zamanda bir A olarak kullanılabilen bir demek) B dışarı çıkabilir ve bu A'un sözleşmesini kırar (sadece int atılır).

+1

Herb Sutter'in bunu (Chris'le aynı fikirde olan) alması için bkz. Http://www.gotw.ca/publications/mill22.htm –

+1

Aslında C++, örtülü işlev bildirimlerinde bunu denetler (doğrudan istisna özelleri, çağrılan fonksiyonun özelliklerini içerir): 'struct A {virtual ~ A() throw(); }; B {~ B() atımı (int) yapısı; }; struct C: A, B {};/* error: ~ C() atıyor (int), ama ~ A() atıyor()! */' –

+0

@Neil: Bağlantı için teşekkürler; Bağlantımı (aslında bir GotW olanı) kullanmak için değiştirdim. :-) –

1

Sizin B Liskov değiştirme prensibi ihlal - örn:

 
void foo(A* a) throw() // ie I will not throw 
{ 
    try 
    { 
    a->f(); 
    } 
    catch(int) 
    {} 
} 

Bu A için arayüze göre geçerlidir; özellikle, bir çiftin atılmasını beklemiyoruz. Ama biz açıkladığınız arayüzü ile

foo(new B)

aramaya olsaydı düşünün ve

B::f()
çift atmak idi.