2013-06-13 3 views
22

그래서 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}; 
} 

답변

6

초기화가 이런 식으로 (C++ 11)을 수행해야합니다 : 또한

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

} 

, 클래스 정의에 생성자를 선언하는 것을 잊지 마세요.

27

C++ 03 스타일

#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() 
     { 
     } 
}; 

parentheses following bar matters. 이 작동 원리를 이해하려면 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 
} 

C++ (11) 스타일 여기

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)의 uniform initialization syntax를 사용합니다. 그러나 이렇게함으로써 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 
} 

은 POD로 myClass을 유지합니다.

집계 및 POD에 대한 자세한 내용은 this excellent post을 참조하십시오.

+3

'struct foo bar;를 놓기 위해 eed했다. C++ 03이나 C++ 11에서는'foo bar;'만이 그렇게 할 것이다. 또한 C++ 11에서는 선언 시점에서'bar'를 초기화 할 수 있습니다. – juanchopanza

+1

동의하고 답변에서 해결했습니다. 그것은 오래된 C 스타일의 struct 객체 선언 구문입니다. – legends2k

+1

OP는 C 헤더 안에'foo'를 명시 적으로 언급하기 때문에 생성자를 추가하는 것은 옵션이 아닙니다. (그리고 C 헤더에'#ifdef __cplusplus '를 넣어서 고치지 마십시오.) –

7

당신이하는 일은 할당이 아니라 초기화입니다.

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 
}; 
초기화 바로 멤버 변수 선언 후 생성자 체 전 또는 C++ 11 이니셜 라이저에서의 생성자의 초기화 목록에서 일어나는

C++ 11 :

MyClass.cpp를

#include "myClass.hpp" 

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

myClass.hpp

extern "C" { 
    #include fileWithStruct.h 
} 

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

이 경우, 당신이 필요가 : 10,403,210 Antoher 옵션은 멤버 변수 선언에서 중괄호 또는 동등한-초기화와 foo는의 초기 값을 제공하는 것입니다 컴파일러에 의해 암시 적으로 생성되므로 (필요한 경우) bar을 올바르게 초기화하므로 생성자를 정의하지 마십시오.

C++ 03 : 당신이 해결 방법을 사용할 필요가 초기화 목록에서

여기에 집계 초기화를 사용할 수없는, 그래서, 예를 들면 :

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 
{ } 
1

foo 구조체에는 "C-linkage"가 있어야합니다. 다음은 완전한 예입니다.

// 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++ 03 버전의 경우를 아직 C++ 11로 이동하지 않았습니다.

#include "myClass.hpp" 

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

C++ 0x는 C++ 11입니다 ... – Griwes

관련 문제