2015-04-20 37 views
17

Nel Mixing C and C++ Code in the Same Program viene fornito il seguente esempio (leggermente abbreviato qui per le parti pertinenti). Si supponga buf.h contiene:Inizializzazione dei membri quando si eredita dalla struttura esterna C

struct buf { 
    char* data; 
    unsigned count; 
}; 

// some declarations of existing C functions for handling buf... 

E 'poi consigliabile utilizzare

extern "C" { 
    #include "buf.h" 
} 

class mybuf : public buf { 
public: 
    mybuf() : data(0), count(0) { } 

    // add new methods here (e.g. wrappers for existing C functions)... 
}; 

al fine di utilizzare la struct all'interno di C++ con le caratteristiche aggiunte.

Tuttavia, chiaramente produrrà il seguente errore:

error: class `mybuf' does not have any field named `data' 
error: class `mybuf' does not have any field named `count' 

Le ragioni sono spiegate in How can I initialize base class member variables in derived class constructor?, C++: Initialization of inherited field e Initialize parent's protected members with initialization list (C++).

Così, ho le seguenti due domande:

  1. è il codice fornito solo chiaramente sbagliato o mi manca qualche aspetto rilevante? (Dopo tutto, l'articolo sembra derivare da una fonte attendibile)
  2. Qual è il modo corretto per ottenere l'effetto desiderato (ad esempio, trasformare una struttura C in una classe C++ e aggiungere alcuni metodi di comodità come, ad esempio, un costruttore, eccetera.)?

Aggiornamento: Utilizzo inizializzazione aggregazione come suggerito, cioè,

mybuf() : buf{0, 0} {} 

opere, ma richiede C++ 11. Pertanto aggiungo la seguente domanda:

  1. Utilizzo di C++ 03, esiste un modo migliore per ottenere il risultato desiderato rispetto all'utilizzo del seguente costruttore?

    mybuf() { 
        data = 0; 
        count = 0; 
    } 
    
+1

Sembra un errore di copia e incolla. In precedenza sulla stessa pagina, l'autore ha implementato una classe 'mybuf' con i membri' data' e 'count'. – dyp

+1

perché inserisci una "C" esterna attorno alla tua struct? non c'è bisogno. –

+1

@CyberSpock Vedere la fonte originale del codice, si tratta di mescolare il codice C e C++ e il file di intestazione contiene alcune dichiarazioni di funzione, ho modificato il codice sopra per chiarirlo. – godfatherofpolka

risposta

8

Se è possibile utilizzare un C++ 11 compilatore compatibile allora questo sarebbe un caso d'uso perfetto per una lista di inizializzazione utilizzando aggregate initialization.

mybuf() : buf{0, 0} 
{} 
+0

Grazie, funziona! Quale sarebbe il modo corretto se non puoi usare C++ 11? – godfatherofpolka

3

Un modo "corretto", se il compilatore C++ è in grado 11, è quello di utilizzare per esempio

mybuf() : buf{0, 0} {} 
+0

Grazie, funziona! Quale sarebbe il modo corretto se non puoi usare C++ 11? – godfatherofpolka

3

Questo non ha nulla a che fare con il missaggio C e C++. Stai cercando di inizializzare i membri che non esistono; che esistano in una classe base non è abbastanza. È necessario inizializzare la base stessa.

In questo caso, utilizzare l'inizializzazione di aggregazione:

class mybuf : public buf 
{ 
public: 
    mybuf() : buf{0, 0} {} 
}; 
+0

Grazie, funziona! Quale sarebbe il modo corretto se non puoi usare C++ 11? – godfatherofpolka

+0

estensione GCC, forse; 'buf ({0,0})' –

2
class mybuf : public buf { 
public: 
    mybuf();  
    // add new methods here (e.g. wrappers for existing C functions)... 
}; 

const buf init = {0,0}; 

mybuf::mybuf() : buf(init) {}; 

funzionerà.

Ho visto questo lavoro con alcuni compilatori, ma non ho uno standard a portata di mano per verificare se è standard o un'estensione.

class mybuf : public buf { 
public: 
    mybuf() : buf(init) { } 

    // add new methods here (e.g. wrappers for existing C functions)... 

    private: 

    const buf init = {0,0}; 
}; 
+0

Per quanto riguarda il tuo secondo metodo: GCC 4.9 [lo accetta] (http://goo.gl/ixNWEG), CLang 3.6rc2 [fornisce un avviso '-Wuninitialized' (http: //goo.gl/yUxcF9) sulla riga del costruttore, ICC 13 [lo rifiuta] (http://goo.gl/GnHkY6) con un errore 409 sulla riga del costruttore e MSVC 17 (VS2012) rifiuta l'inizializzatore con un C2059 'errore inatteso {' seguito da C2334 'token imprevisti che precedono' {'' e quindi un 'identificatore non dichiarato' C2065 alla definizione del costruttore. Direi che è un'estensione GCCism/GCC, o UB. – LThode