8

Ecco una classe con un metodo non definito. Sembra compilatori consentono istanze di questa classe per essere costruiti, a condizione che la funzione di membro non definita non viene mai chiamato:Sono consentiti tutti i metodi non definiti non utilizzati?

struct A { 
    void foo(); 
}; 

int main() { 
    A a;  // <-- Works in both VC2013 and g++ 
    a.foo(); // <-- Error in both VC2013 and g++ 
} 

Ecco una situazione simile, ma che coinvolge l'ereditarietà. Sottoclasse Bar estende la classe base . Foo definisce un metodo g(). Bar dichiara lo stesso nome metodo, ma non la definisce:

#include <iostream> 

struct Foo { 
    void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    void g(); 
}; 

int main() { 
    Bar b;  // Works in both VC2013 and g++ 
    b.Foo::g(); // Works in both VC2013 and g++ 
    b.g();  // Error in both VC2013 and g++ 
} 

Ecco una variazione di quanto sopra. L'unica differenza è che qui è g()virtual sia Foo e Bar:

#include <iostream> 

struct Foo { 
    virtual void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    virtual void g(); 
}; 

int main() { 
    Bar b;  // Works in g++. But not in VC2013, which gives 
       // 'fatal error LNK1120: 1 unresolved externals' 

    b.Foo::g(); // Works in g++, but VC2013 already failed on b's construction 
    b.g();  // Error in g++, but VC2013 already failed on b's construction 
} 

Vedi le osservazioni di codice per il contrasto di un comportamento differente tra il VC2013 e g ++.

  1. Quale compilatore è corretto, se presente?
  2. Perché il compilatore di VC2013 ha alcuni reclami diversi nella sua versione con la parola chiave virtual rispetto a quella nella sua versione senza la parola chiave virtual?
  3. Sono sempre consentiti metodi non definiti non utilizzati? In caso contrario, quali sono tutti i casi in cui sono non consentiti?
  4. La dichiarazione Bar di g() conta come prioritaria anche se Bar non fornisce una definizione?
+0

Il vtable fa riferimento al costruttore e ha bisogno degli indirizzi delle funzioni virtuali, quindi l'errore di VC2013 sembra ragionevole. – BartoszKP

risposta

8

Quale compilatore è corretto, se presente?

Hanno entrambi ragione. Il tuo codice è sbagliato, nessuna diagnostica richiesta. [Class.virtual]/11

Una funzione virtuale dichiarata in una classe sono definite, o dichiarato puro (10.4) in questa categoria, o entrambi; ma non è richiesta alcuna diagnostica (3.2).

[intro.compliance]/2:

Se un programma contiene una violazione di una regola per la quale non diagnostico è richiesto, questi luoghi International Standard alcun obbligo in implementazioni rispetto a quella programma.

Dai un'occhiata alle tue impostazioni di ottimizzazione per GCC, possono influenzare il comportamento.


sono metodi non definiti non utilizzati sempre permesso?

È necessario definire una funzione membro se e solo se è utilizzata odr. [Basic.def.ODR]/3:

Ogni programma deve contenere esattamente un definizione di ogni non-inline funzione o variabile che è ODR-utilizzati in tale programma; nessuna diagnostica richiesta.

consideri ora [basic.def.odr]/2:

Un'espressione è valutata potenzialmente meno che non sia un operando non valutata (punto 5) o una sottoespressione loro.
[...]
Una funzione membro virtuale viene utilizzata odr se non è pura.
Una funzione non sovraccaricata il cui nome appare come espressione potenzialmente valutata o un membro di un insieme di funzioni candidate, se selezionato dalla risoluzione di sovraccarico quando riferito da un'espressione potenzialmente valutata, viene utilizzato odr, a meno che non sia un pura funzione virtuale e il suo nome non è esplicitamente qualificato.

Siete ancora il permesso di utilizzare le funzioni di membro non virtuali non definiti all'interno decltype o sizeof. Ma le funzioni virtuali non pure sono usate odr semplicemente perché non sono pure.


dichiarazione di g di non Bar() conta come ignorando anche quando Bar non fornisce una definizione?

Sì.

+0

Riguardo, "Hanno entrambi ragione", vuoi dire che è ok per g ++ costruire correttamente 'b' (la cui classe ha il metodo virtuale) mentre VC2013 non può, perché è un comportamento non specificato? – CodeBricks

+1

@CodeBricks È praticamente identico al comportamento non definito. Controlla [questa risposta] (http://stackoverflow.com/questions/22180312/difference-between-undefined-behavior-and-ill-formed-no-diagnostic-message-requ). – Columbo

+0

Significa che non è necessario chiamare una funzione virtuale non pura per essere utilizzata odr? – CodeBricks

Problemi correlati