2015-04-20 2 views
17

In Mixing C and C++ Code in the Same Program wird das folgende Beispiel (hier zu den relevanten Teilen leicht abgekürzt) gegeben. Angenommen, buf.h enthält folgende Komponenten:Initialisierung von Elementen beim Erben von extern C struct

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

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

Es wird dann empfohlen

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)... 
}; 

zu verwenden, um die Struktur in C++ mit zusätzlichen Funktionen zu verwenden.

Dies ist jedoch eindeutig den folgenden Fehler erzeugen:

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

Die Gründe dafür erläutert in How can I initialize base class member variables in derived class constructor?, C++: Initialization of inherited field und Initialize parent's protected members with initialization list (C++).

So, ich habe die beiden folgenden Fragen:

  1. Ist der Code nur einfach falsch versehen oder bin ich einige relevante Aspekt fehlt? (Schließlich scheint der Artikel von einer seriösen Quelle zu stammen)
  2. Was ist der richtige Weg, um den gewünschten Effekt zu erzielen (dh, eine C-Struktur in eine C++ - Klasse umzuwandeln und einige bequeme Methoden wie z. B. einen Konstruktor hinzuzufügen, etc.)?

aktualisieren: Mit Aggregation Initialisierung, wie vorgeschlagen, das heißt

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

Werke, sondern erfordert C 11 ++. Ich füge daher die folgende Frage hinzu:

  1. Mit C++ 03 gibt es eine bessere Möglichkeit, das gewünschte Ergebnis zu erzielen als mit dem folgenden Konstruktor?

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

Sieht aus wie ein Copy & Paste Bug. Zuvor hat der Autor eine Klasse 'mybuf' mit' data'- und 'count'-Membern implementiert. – dyp

+1

Warum legen Sie ein externes "C" um Ihre Struktur? Es besteht kein Bedarf. –

+1

@CyberSpock Siehe die ursprüngliche Quelle des Codes, dies ist über Mischen von C-und C++ - Code und die Header-Datei enthält einige Funktionsdeklarationen, ich habe den Code oben, um dies klar zu machen. – godfatherofpolka

Antwort

8

Wenn Sie ein C++ 11 kompatible Compiler verwenden können, dann wäre dies ein perfekter mit aggregate initialization Anwendungsfall für eine Initialisiererliste sein.

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

Danke, das funktioniert! Was wäre der richtige Weg, wenn Sie C++ 11 nicht verwenden können? – godfatherofpolka

3

Ein "richtiger" Weg, wenn Ihr Compiler C++ 11 fähig ist, ist z.

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

Danke, das funktioniert! Was wäre der richtige Weg, wenn Sie C++ 11 nicht verwenden können? – godfatherofpolka

3

Dies hat nichts mit Mischen von C und C++ zu tun. Sie versuchen, Mitglieder zu initialisieren, die nicht existieren. dass sie in einer Basisklasse existieren, ist nicht genug. Sie müssen die Basis selbst initialisieren.

In diesem Fall verwenden Aggregat Initialisierung:

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

Danke, das funktioniert! Was wäre der richtige Weg, wenn Sie C++ 11 nicht verwenden können? – godfatherofpolka

+0

GCC-Erweiterung, vielleicht; '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) {}; 

arbeiten.

Ich habe gesehen, dass dies mit einigen Compilern funktioniert, aber kein Standardhandy hat, um zu überprüfen, ob es Standard oder eine Erweiterung ist.

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

Zu Ihrer zweiten Methode: GCC 4.9 [akzeptiert es] (http://goo.gl/ixNWEG), CLang 3.6rc2 [gibt eine '-Wuninitialized'-Warnung] (http: //goo.gl/yUxcF9) in der Konstruktorzeile, ICC 13 [lehnt es ab] (http://goo.gl/GnHkY6) mit einem Fehler 409 in der Konstruktorzeile, und MSVC 17 (VS2012) weist den Initialisierer mit a zurück C2059 'Unerwarteter {' Fehler gefolgt von C2334 'unerwarteten Token vor' {'' und dann ein C2065 'nicht deklarierter Bezeichner' in der Konstruktordefinition. Ich würde sagen, es ist entweder eine GCCism/GCC-Erweiterung oder UB. – LThode