そこで、Cヘッダーファイルの構造体をクラスメンバーとしてc ++クラスに追加します。しかし、cpp
ファイルのコンパイラエラーが発生します:bar was not declared inn this scope
。これは私が持っているものです:
// 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};
}
#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()
{
}
};
bar
の後に続く括弧 。 value and zero-initialization を参照して、これが機能する理由を理解してください。コンストラクタをmyClass
に追加することにより、非POD型にしたことに注意してください。これを回避するには、myClass
を集約として保持し、次のように記述します。
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
}
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;
};
ここでは、C++ 11の 均一な初期化構文 を使用します。ただし、これを行うと、myClass
は非POD型になります。メンバーの初期化は、コンストラクターをクラスに追加することと似ており、それによってmyClass
を単純ではないが標準レイアウトのクラスにレンダリングします。クラスがPODになるためのC++ 11に従って、それは取るに足りない標準レイアウトでなければなりません。代わりに
#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
}
myClass
をPODとして保持します。
集約とPODの詳細については、 この優れた投稿 を参照してください。
そこで行うことは、初期化ではなく割り当てです。初期化は、コンストラクターの初期化リスト、コンストラクター本体の前、またはメンバー変数宣言の直後の初期化子のC++ 11で行われます。
myClass.hpp、一般的なケース:
/** 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
};
myClass.cpp
#include "myClass.hpp"
//Initialize structure in Constrcutor
myClass::myClass( )
: bar{1, 0, "someString", 0x4}
{}
他のオプションは、fooの初期値にbrace-or-equal-initializerをメンバー変数宣言で提供することです。
myClass.hpp
extern "C" {
#include fileWithStruct.h
}
class myClass
{
public:
foo bar{1, 0, "someString", 0x4};
};
この場合、コンストラクターを暗黙的に生成し(必要な場合)、bar
を正しく初期化するため、コンストラクターを定義する必要はありません。
ここでは、初期化リストでの集計の初期化は使用できないため、次のような回避策を使用する必要があります。
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;
}
または:
#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
{ }
初期化は次の方法で行う必要があります(C++ 11):
myClass::myClass( )
: bar{1, 0, "someString", 0x4}
{
}
また、クラス定義でコンストラクターを宣言することを忘れないでください。
Foo構造体に「Cリンケージ」を指定する必要があります。以下は完全な例です。
// 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
MyClassヘッダーファイル:
// myClass.hpp
#include "fileWithStruct.h"
class myClass
{
public:
myClass();
foo bar;
};
拡張初期化子リストを使用するmyClassのC + 11実装:
// myClass.cpp
#include "myClass.hpp"
myClass::myClass( )
: bar({1, 0, "someString", 0x4})
{
}
... C++ 11にまだ移行していない場合は、C++ 03バージョン:
#include "myClass.hpp"
myClass::myClass( )
: bar()
{
bar.a = 1;
bar.b = 0;
bar.c = "someString";
bar.d = 0x4;
}