2013-06-13 13 views
22

Also ich möchte eine Struktur aus einer c-Header-Datei als Klassenmitglied zu einer C++ - Klasse hinzufügen. Aber ich bekomme einen Compilerfehler für die cpp Datei: bar was not declared inn this scope. Das ist, was ich habe:Korrekte Art der Initialisierung einer Struktur in einem Klassenkonstruktor

// myClass.hpp 
#include fileWithStruct.h 

class myClass 
{ 
    public: 
     struct foo bar; 
}; 


//myClass.cpp 

#include "myClass.hpp" 

//Initialize structure in Constrcutor 
myClass::myClass() 
{ 
    bar = {1, 0, "someString", 0x4}; 
} 

Antwort

6

Initialisierung sollte auf diese Weise durchgeführt werden (C++ 11):

myClass::myClass() 
: bar{1, 0, "someString", 0x4} 
{ 

} 

Auch vergessen Sie nicht, Ihren Konstruktor in Ihrer Klassendefinition zu erklären.

27

C++ 03-Art

#include "fileWithStruct.h" 
/* say the contents were 
struct foo 
{ 
    int foo1; 
    float foo2; 
}; 
*/ 

class myClass 
{ 
    public: 
     int val; 
     foo bar; 
     // since foo is a POD-struct (a.k.a C struct), no constructor would be present 
     // however bar() will zero-initialize everything in the struct 
     myClass() : val(), bar() 
     { 
     } 
}; 

Die parentheses following bar matters. Sehen Sie sich value and zero-initialization an, um zu verstehen, warum das funktioniert. Es ist zu beachten, dass wir durch Hinzufügen eines Konstruktors zu myClass einen Nicht-POD-Typ erstellt haben. Um dies zu umgehen, kann man myClass als Aggregat erhalten und schreiben:

class myClass 
{ 
    public: 
     int val; 
     foo bar; 
}; 

int main() 
{ 
    myClass zeroed_obj = { }; 
    myClass inited_obj = { 2, {0, 1.0f} }; 
    myClass partially_inited_obj = { 2 }; // equivalent to {2, {}}; which would zero all of myClass::bar 
    myClass garbage_obj; // warning: when left uninitialized, every member without a constructor will end up with garbage value 
} 

C++ 11-Art

class myClass 
{ 
public: 
    // default member initializations 
    int val = { };   // zero-initialization 
    foo bar = { 0, 0.0f }; // aggregate-initializing foo here, just giving { } will zero all of myClass::bar 

    // should you want to receive an element from the constructor, this can be done too 
    // aggregate initializing a struct in constructor initialization list is allowed from C++11 onwards 
    // in C++03, we would've resorted to just setting the member of bar inside the constructor body 
    myClass(int _foo1) : bar{_foo1, 0.f}, val{} 
    { 
    } 

    // since we've a non-default constructor, we've to re-introduce the default constructor 
    // if we need the above in-class initialization to work 
    myClass() = default; 
}; 

Hier verwenden wir C++ 11 die uniform initialization syntax. Dadurch wird myClass jedoch ein Nicht-POD-Typ; Die Elementinitialisierung ähnelt dem Hinzufügen eines Konstruktors zur Klasse, wodurch myClass eine nicht-triviale Standardlayoutklasse dargestellt wird. Gemäß C++ 11 für eine Klasse, die POD sein soll, sollte es sowohl trivial als auch Standard-Layout sein. Stattdessen

#include "fileWithStruct.h" 
#include <type_traits> 
#include <iostream> 

class myClass 
{ 
public: 
    int val; 
    foo bar; 
}; 

int main() 
{ 
    myClass obj { }; // initializes val, bar.foo1 and bar.foo2 to 0 
    myClass m { 0, {1, 2.0f} }; // initilizes each member separately 
    std::cout << std::is_pod<myClass>::value << std::endl; // will return 1 
} 

wird behalten myClass als POD.

Weitere Informationen zu Aggregaten und PODs finden Sie unter this excellent post.

+3

Sie n nicht: Sie haben nicht zu C++ 11 noch bewegt eed to sat 'struct foo bar;' in C++ 03 oder C++ 11 genügt 'foo bar;'. In C++ 11 können Sie auch 'bar' zum Zeitpunkt der Deklaration initialisieren. – juanchopanza

+1

Einverstanden, fixierte es in der Antwort. Das ist eine alte C-style-Deklaration für Strukturobjekte. – legends2k

+1

Das OP erwähnt ausdrücklich, dass "foo" in einem C-Header enthalten ist, daher ist das Hinzufügen eines Konstruktors keine Option. (Und bitte beheben Sie das nicht, indem Sie '#ifdef __cplusplus' in die C-Kopfzeile setzen) –

7

Was Sie dort tun, ist die Zuweisung, nicht die Initialisierung. Initialisierung geschieht in der Initialisierungsliste eines Konstruktors, vor dem Konstruktor des Körpers oder in C++ 11 in einem Initialisierer direkt nach der Elementvariablen Deklaration:

myClass.hpp, allgemeiner Fall:

/** you might want to do this if you are linking 
* against the C lib or object file of that header: 
*/ 
extern "C" { 
    #include fileWithStruct.h 
} 

class myClass 
{ 
public: 
    foo bar; //no need for "struct" in C++ here 
}; 

C++ 11:

MyClass.cpp

#include "myClass.hpp" 

//Initialize structure in Constrcutor 
myClass::myClass() 
    : bar{1, 0, "someString", 0x4} 
{} 

Antoher Option ist, den Anfangswert von foo mit einem Klammer-oder-gleich-initializer an der Membervariable Erklärung zu liefern:

myClass.hpp

extern "C" { 
    #include fileWithStruct.h 
} 

class myClass 
{ 
public: 
    foo bar{1, 0, "someString", 0x4}; 
}; 

In diesem Fall müssen Sie Definieren Sie keinen Konstruktor, da dieser implizit vom Compiler generiert wird (falls erforderlich) und bar korrekt initialisiert wird.

C++ 03:

Hier Aggregat Initialisierung in init-Listen ist nicht verfügbar, so dass Sie Abhilfen verwenden, zB:

MyClass.cpp

#include "myClass.hpp" 

//Initialize structure in Constrcutor 
myClass::myClass() 
    : bar() //initialization with 0 
{ 
    const static foo barInit = {1, 0, "someString", 0x4}; //assignment 
    bar = barInit; 
} 

Oder:

#include "myClass.hpp" 
namespace { 
    foo const& initFoo() { 
    const static foo f = {1, 0, "someString", 0x4}; 
    return f; 
    } 
} 

//Initialize structure in Constrcutor 
myClass::myClass() 
    : bar(initFoo()) //initialization 
{ } 
1

Sie müssen dies angeben Die foo-Struktur sollte "C-Verknüpfung" haben. Das Folgende ist ein vollständiges Beispiel.

// fileWithStruct.h 
#ifdef __cplusplus 
extern "C" { // Declare as extern "C" if used from C++ 
#endif 

typedef struct _foo 
{ 
    int a; 
    int b; 
    const char* c; 
    int d; 
} foo; 


#ifdef __cplusplus 
} 
#endif 

Die myClass Header-Datei:

// myClass.hpp 
#include "fileWithStruct.h" 

class myClass 
{ 
public: 
    myClass(); 

    foo bar; 
}; 

Die C + 11 Implementierung von myClass die Listen erweiterten initializer verwendet:

// myClass.cpp 
#include "myClass.hpp" 

myClass::myClass() 
    : bar({1, 0, "someString", 0x4}) 
{ 
} 

... und die C++ 03-Version, wenn

#include "myClass.hpp" 

myClass::myClass() 
    : bar() 
{ 
    bar.a = 1; 
    bar.b = 0; 
    bar.c = "someString"; 
    bar.d = 0x4; 
} 
+3

C++ 0x ist C++ 11 ... – Griwes

Verwandte Themen