2012-05-24 12 views
9

Załóżmy, że mam:Jaka jest specyfikacja wyjątku dla domyślnego wirtualnego destruktora w C++ 11?

class Foo 
{ 
public: 
    virtual ~Foo()=default; 
}; 

Co jest wyjątkiem specyfikacją na niewykonaniem destructor? Czy defaulted destructor równoważne:

virtual ~Foo() {}; 
or 
    virtual ~Foo() throw() {}; 
or 
    virtual ~Foo() noexcept {}; 

rozdziale 15.4 standardu C++ 11 mówi, że to zależy od specyfikacji wyjątkiem funkcji bezpośrednio powoływane przez niejawny definicji destruktor jest. W tym przypadku nie ma żadnych członków i klas podstawowych, więc AFAIK nie ma żadnych funkcji bezpośrednio wywoływanych przez niejawny destruktor. Czy jest to niejednoznaczność (lub pominięcie) w standardzie?

Ma to znaczenie, ponieważ jeśli niejawnie ma throw(), wówczas wszystkie podklasy muszą zadeklarować swoje destruktory za pomocą throw(). Nie mów mi, że to zły pomysł na wyrzucanie wyjątków w destruktorach, wiem o tym. Mam do czynienia z dużą ilością starszego kodu, w którym specyfikacje wyjątków nie były w ogóle używane.

Jako punkt informacji, kiedy próbowałem:

class SubFoo : public Foo 
{ 
public: 
    virtual ~SubFoo(); 
}; 

mam błąd (niedopasowane specyfikację wyjątku) w GCC 4.4 (chociaż muszę przyznać, że nie może mieć przełączniki linii poleceń po prawej), ale nie w XCode 4.3 przy użyciu kompilatorów "11".

Odpowiedz

4

Powrót do wcześniej w tym samym zdaniu (§15.4/14):

... jej niejawny wyjątek-specyfikacja określa typ-id T wtedy i tylko wtedy, gdy T jest dozwolone przez exception- określenie funkcji bezpośrednio powoływane przez niejawny definicji f jest; ...”

Dlatego jeśli ~Foo nie wywoływać żadnych funkcji, ma niejawny deklarację, która pozwala bez wyjątków być rzucony

według. do §15.4/3:

Dwa wyjątku specyfikacji są zgodne, jeżeli:

  • oba są non-rzucanie (patrz poniżej), niezależnie od ich formy,

To w tym przypadku, więc nie ma znaczenia, czy deklaracja jest throw() czy noexcept - oba są kompatybilne w każdym przypadku.

+0

Dziękuję za odpowiedź. Aby śledzić nieco więcej, specyfikacja mówi: "Deklaracja destruktora, który nie ma specyfikacji wyjątków, jest domyślnie uważana za zawierającą tę samą specyfikację wyjątku co domyślna deklaracja" Tak więc "virtual ~ SubFoo();" (bez wyjątku spec) nie jest źle sformułowany, chyba że bezpośrednio wywołuje funkcje, które pośrednio lub jawnie pozwalają na rzucanie? – user1414050

+0

@ user1414050: Uważam, że to prawda, tak - ale my " dostaję się na tyle zakątków języka, że ​​nie postawiłbym zbyt wiele na większość kompilatorów, co jest w tej chwili poprawne. W szczególności, podejrzewam, że wiele (większość?) kompilatorów traktuje 'virtual ~ SubFoo();' w znaczeniu "może rzucać cokolwiek ", tak jak przy normalnej funkcji –

+0

Myślę, że ten wniosek może nie mieć, ponieważ" jeśli i tylko jeśli "jest sprzeczne z następującym zdaniem częściowym dotyczącym allowin g wszystkie wyjątki (to jest standard tutaj jest sprzeczny). I myślę, że to jest wątpliwe, czy intencją jest, aby destruktory domyślnie nie miały rzutu. Ponieważ byłoby to niezgodne z C++ 03. –

2

standardese zaczyna ładnie w C++ 11 §8.4.2/2,

Jeśli funkcja jest wyraźnie wywiąże się ze swoim pierwszym oświadczeniu
- jest domyślnie uznawane za constexpr jeśli domyślna deklaracja będzie,
- domyślnie uważa się, że ma taką samą specyfikację wyjątków, jak gdyby została domyślnie zadeklarowana (15.4), & hellip;

Ale potem, w C++ 11 §15.4/14 logika szybko nakładanych,

niejawnie uznane specjalną funkcję użytkownika (punkt 12) powinny mieć wyjątku specyfikacją. Jeśli f jest domyślnie deklarowanym konstruktorem domyślnym, konstruktorem kopiowania, konstruktorem ruchu, destruktorem, operatorem przypisania kopiowania lub operatorem przypisania, jego specyfikacja wyjątku wyjątkowego określa identyfikator typu T, jeśli jest dozwolona tylko przez specyfikację wyjątku. funkcji bezpośrednio wywoływanej przez domyślną definicję f; f zezwala na wszystkie wyjątki, jeśli jakakolwiek funkcja, którą wywołuje bezpośrednio, dopuszcza wszystkie wyjątki, a f nie dopuszcza żadnych wyjątków, jeśli każda funkcja, do której się bezpośrednio wywołuje, nie dopuszcza żadnych wyjątków.

W rozumieniu standardu "dopuszczaj" chodzi o jawne dopuszczenie, poprzez specyfikację wyjątku.

Jeśli f wywołuje dwie funkcje, z których jeden precyzuje i dlatego pozwala T, a jeden, który pozwala wszystkie wyjątki, a następnie f musi określić zarówno Ti pozwolić wszystkie wyjątki, które ISN ’ t możliwe.

To zdecydowanie wygląda na wadę standardu.

Znalazłem powiązany raport o defekcie, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1351.

Wygląda jednak na to, że ten obszar jest po prostu wielkim bałaganem. :-(

+0

@anonymous downvoter: wyjaśnij swoje zdanie, aby inni mogli uczyć się na podstawie twojego wglądu. –

+0

Dla mnie nie wygląda jak DR; oznacza to tylko, że musisz wziąć pod uwagę, że 'specyfikacja wyjątków określa T 'jako podzbiór' zezwól na wszystkie wyjątki'. – MSalters

+0

@MSalters: nie ma na to żadnej składni? –

Powiązane problemy