Domanda

ho visto il seguente frammento di codice:

class Foo
{
public:
        void virtual func() throw (int, float) = 0;
};

class Bar : public Foo
{
public:
        void virtual func() throw(short);      // line 1: compile error "
                                                                      // looser throw specifier"
        void virtual func() throw();                // line 2: can compile
        void virtual func() throw(float, int); // line 3: can compile
        void virtual func() throw(float);        // line 4: can compile
        void virtual func() throw(int);           // line 5: can compile

};

int main(void)
{
        return 1;
}

Q1> Qual è il significato di

void virtual func() throw (int, float) = 0;

Q2> perchè linea 1 non può passare il compilatore?

Grazie

È stato utile?

Soluzione

pausa Let questo giù. La dichiarazione:

void virtual func() throw (int, float) = 0;

ha 2 costrutti che si sta chiedendo. il costrutto =0 dice al compilatore che la funzione dichiarata è 'astratto', che dice al compilatore che la funzione non deve essere definito nel class Foo (anche se può essere - ma di solito non lo è) e che un oggetto di class Foo non può essere direttamente creato - sia come un locale, globale o tramite new. Tuttavia, è possibile avere puntatori o riferimenti a oggetti di class Foo. Alcune esigenze classe derivata per ignorare la funzione come una funzione non astratta -. Oggetti di quella classe possono essere creati direttamente (a patto che non ci sono altre funzioni astratte che non sono state fatte 'concreta')

Il costrutto throw (int, float) è uno specifification un'eccezione. Questo dice al compilatore che il contratto della funzione è che getterà solo eccezioni di tipo int o float se viene generata un'eccezione. Se la funzione lancia un altro tipo di eccezione, il compilatore è obbligato a gestire questo particolare (chiamando std::unexpected()).

Ora, se si tenta di ignorare che la funzione in una classe derivata con la seguente dichiarazione:

void virtual func() throw(short);

Stai dicendo che il contratto della funzione è che sarà generare eccezioni di tipo short se viene generata un'eccezione. Tuttavia, gettando short non è parte del contratto della funzione di essere sottoposto a override, in modo che il compilatore non lo consente.

Se si dichiara la sostituzione in questo modo:

void virtual func() throw(float);

Stai dicendo che l'override può gettare un float, che fa parte del contratto della dichiarazione originale (se non si è mai genera int che non si rompe il contratto - il contratto originale dice solo che è consentita la funzione per lanciare un int, non che ha a).

La parte rilevante dello standard è 15,4 / 3 specifiche di eccezione:

  

Se una funzione virtuale ha un   specifica delle eccezioni, tutti i   dichiarazioni, tra cui il   definizione, di qualsiasi funzione che   sostituzioni tale funzione virtuale in qualsiasi   classe derivata membri autorizzano   eccezioni che sono autorizzati dal   specifica delle eccezioni della base   funzione virtuale di classe.

Si noti che la norma afferma esplicitamente che una specifica eccezione non fa parte del tipo della funzione (15.4 / 12), quindi un puntatore a funzione può, ad esempio, scegliere funzioni che hanno diverse specifiche eccezioni.

Altri suggerimenti

Si sta definendo la stessa firma funzione molte volte. Le diverse qualificazioni throw() non sono sufficienti per disambiguare le funzioni.

Il qualificatore throw() significa semplicemente che la funzione specificata è previsto solo per gettare le tipologie elencate tra parentesi dopo il qualificatore. Tuttavia, questo in realtà non impedisce la funzione da buttare. Piuttosto, se la funzione in realtà non gettare qualsiasi tipo non quotate, il programma terminerà.

La funzione che si sta definendo nella classe base è fare una garanzia - può lanciare solo un int o un float. La vostra linea 1 sta fallendo perché è rompendo la garanzia dicendo che lancerà una short, che non è né di quanto sopra.

Il = 0 in Q1 dichiara che ogni classe derivata che si tenta di creare un'istanza di necessità volontà di fornire la propria dichiarazione e implementazione di questa funzione. La classe di base può anche fornire un'implementazione, ma in genere non è così.

Il significato delle dichiarazioni throw nome è quello di dichiarare che una funzione può lanciare solo quelli nominati eccezioni, direttamente o indirettamente.

Così la linea:

void virtual func() throw(int, float) =0;

significa che qualsiasi cosa eredita classe questo tipo di base è consentito solo a buttare sia un int o un float. Non può né gettare direttamente o indirettamente, qualsiasi altro tipo di eccezione o di un oggetto. Se lo fa, chiamerà la funzione unexcepted(). Per impostazione predefinita, questo chiama la funzione terminate(). Si è permesso di ripristinare che utilizza la funzione set_unexpected ma ancora.

Con la scelta di aggiungere tali dichiarazioni tiro alla vostra interfaccia si sta limitando di te stesso.

Quando si ignora una funzione virtual qualsiasi specificatore eccezione che fornito deve essere almeno altrettanto restrittiva come quella indicata sulla funzione che si sta prevalente. Questo impedisce la classe base di specifica eccezione venga violata.

Come la classe base eccezione identificatore [throw (int, float)] non permette un short ad essere gettato, la classe derivata non può consentire a un short per essere gettato. Al massimo si può permettere un int e / o un float; essa può consentire solo una o né essere gettato come qualsiasi di queste possibilità sarebbe più restrittiva rispetto alla specifica eccezione della funzione classe base.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top