2015-06-05 17 views

risposta

7

[class.virtual]/P7, l'enfasi è mia:

Il tipo di ritorno di una funzione preponderante sarà sia identico al il tipo di ritorno della funzione ignorata o covariante con le classi delle funzioni. Se una funzione D::f sostituisce una funzione B::f, i tipi di ritorno delle funzioni sono covarianti se soddisfano i seguenti criteri:

  • entrambi sono puntatori alle classi, entrambi sono riferimenti lvalue a classi, o entrambi sono riferimenti a rvalue classi [omissis] nota
  • [...]

Dalle pagine 294-5 di D&E:

Afer qualche considerazione delle alternative, abbiamo deciso di consentire prioritario di una B* da un D* e di un B& da un D& dove B è un base accessibile di D. Inoltre, è possibile aggiungere const o sottratto ovunque sia sicuro. Abbiamo deciso di non rilassarsi le regole per consentire conversioni tecnicamente fattibile come un D ad un accessibile base di B, un D ad un X che D ha una conversione, int* a void*, double a int, ecc Riteniamo che i vantaggi di che consentono tali conversioni tramite override non superano il costo di implementazione e il potenziale per utenti confusi.

+2

Sarebbe bello se potessi spiegare il "perché" di questo progetto. – Mehrdad

+1

@ Mehrdad Aggiunto un preventivo D & E. –

+0

Quando guardo al problema con la covarianza e le limitazioni degli spazi dei nomi in C++, posso discernere il ragionamento dietro l'oggetto e i pacchetti di Java. – ady

0

La funzione di tipo di ritorno covariant è quando, una classe derivata fornisce un tipo di ritorno più specifico/più stretto per una funzione sostituita. Il tipo restituito della classe derivata è detto covariante.

int * non è di tipo void * che qualcosa di simile non raffigurano covariante tipo di ritorno:

struct Base { 
    virtual void *foo(); 
    virtual Base* func(); 
}; 
struct Derived : Base { 
// int *foo(); 
    Derived* func(); //COVARIANT RETURN TYPE 
}; 
+0

Stai spiegando la definizione di "Covarianza", l'OP sta chiedendo "Perché". – iammilind

1

La covarianza tra void* e T* non è consentito perché:

1. mancanza di coerenza.

L'attuale modo di covarianza è banale da comprendere e non crea confusione.
Immaginate solo il tipo di covarianza void*. Per 1 stadio di derivazione va bene, ma poi creerà confusione. es .:

struct void_ { virtual void* foo(); }; 
struct int_ : void_ { virtual int* foo(); }; 
struct double_ : int_ { virtual double* foo(); }; // int* to double* or void* to double* 

Nel 3 ° gerarchia di struct double_, l'utente sarà confuso che anche se double* a int* non è possibile, perché il codice è ancora la compilazione? Solo dopo aver controllato la parte più alta della classe void_, è noto che è a causa di double* a void* è "covariante". Lo stesso vale per il compilatore così :-)

2. Problema con i riferimenti

In caso di classi, di ritorno B&/D*/DD* è possibile. Ma la stessa cosa non è possibile con void& e quindi int& ecc

3. Miscele di covarianze

Se void* è consentito poi seguito è consentito anche involontariamente.

struct void_ { virtual void* foo(); }; 
struct Base : void_ { virtual Base* foo(); }; 
struct Derived : Base { virtual int* foo(); }; // Look at `int*` 

Il che aggiunge confusione.

Problemi correlati