2015-02-28 12 views
7

Per quanto riguarda le domande precedenti su questo argomento:Clang -Wweak-VTables e pura classe astratta

Questo è un follow-up della domanda che ho chiesto di recente: clang: no out-of-line virtual method definitions (pure abstract C++ class) , e che è stato contrassegnato come duplicato di questa domanda: What is the meaning of clang's -Wweak-vtables?. Non penso che questo abbia risposto alla mia domanda, quindi qui mi concentro sulla cosa che mi imbarazza e che non ha ancora ricevuto risposta.

mio scenario:

Sto cercando di compilare il codice seguente semplice C++ usando Clang-3.5:

test.h:

class A 
{ 
    public: 
    A(); 
    virtual ~A() = 0; 
}; 

test.cc

#include "test.h" 

A::A() {;} 
A::~A() {;} 

Il comando che utilizzo per compilarlo (Li nux, uname -r: 3.16.0-4-amd64):

$clang-3.5 -Wweak-vtables -std=c++11 -c test.cc 

E l'errore che ottengo:

./test.h:1:7: warning: 'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables] 

Il codice di cui sopra si basa bene quando la classe A non è puro astratto. Il seguente codice non emette avvisi, e l'unico cambiamento è che la classe A non è più astratto:

test2.h:

class A 
{ 
    public: 
    A(); 
    virtual ~A(); 
}; 

test2.cc

#include "test2.h" 

A::A() {;} 
A::~A() {;} 

La mia domanda

Cosa c'è di così speciale in classi astratte pure che il codice precedente attiva rongi a Clang?

+0

Nel tuo secondo esempio, 'A' non è affatto astratto –

+0

Cosa pensi che succederebbe se non avessi definizione di A :: ~ A'? Quindi, se il compilatore attendesse di vedere una definizione di 'A :: ~ A' per emettere il vtable, non ci sarebbe alcun vtable! – immibis

+1

@immibis che comportamento corretto non è vero? (altri TU compresi test2.h arriveranno alla stessa conclusione) –

risposta

4

Una classe con metodi virtuali ha sempre bisogno di emettere un vtable. Il compilatore ha bisogno di un'indicazione su dove memorizzare il vtable - di solito nell'oggetto che implementa la sua prima funzione.

Cosa c'è di così speciale in classi pure astratte? Poiché non hanno metodi, il compilatore deve emettere un vtable in ogni unità di traduzione in modo che ogni unità di traduzione possa riferirsi al puro tipo di base astratto. Questo è ciò che l'avvertimento ti sta dicendo.

Ad esempio, si potrebbe desiderare di evitare di duplicare quella memoria in un ambiente di memoria molto basso, o se si guardano gli oggetti e ci si chiede perché ci siano più copie del vtable intorno al luogo.

In ogni caso, il fatto che sia possibile utilizzare un puntatore polimorfico su un oggetto A significa che il compilatore deve emettere alcune informazioni su quel tipo — del vtable.

È possibile disattivare l'avviso per quel blocco con Clang's diagnostic pragmas se ti piace:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wweak-vtables" 
class A { 
public: 
    virtual void doSomething() = 0; 
    virtual ~A() = 0; 
}; 
#pragma clang diagnostic pop 

Questo è il tuo dilemma: o rendere la classe non-puri-astratto, o disattivare l'avviso. A seconda delle tue esigenze potresti preferire l'uno o l'altro, ma come con tutti gli avvertimenti dovresti considerarlo attentamente.

+0

Da quando le classi astratte pure non hanno metodi? –

+1

@Andrzej Classe astratta = almeno un metodo virtuale puro. Pure abstract class == interface => tutto il metodo è puro virtuale? –

+0

@Ted Sono ancora confuso. In entrambi i miei esempi definisco A :: ~ A() (e infatti A :: A()). Com'è equivalente ad avere _no_ metodi? E perché l'eliminazione del costruttore risolve anche il problema: 'classe A pubblica: virtual ~ A() = 0; }; '(supponiamo che A :: A() sia eliminato anche in test.cc)? –