所以我想从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};
}
答案 0 :(得分:31)
#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
}
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
成为一个非平凡但标准的布局类。根据C ++ 11,对于要成为POD的类,它应该是平凡的和标准的布局。而是做
#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。
请参阅this excellent post以了解有关聚合和POD的更多信息。
答案 1 :(得分:9)
你在做什么是分配,而不是初始化。初始化发生在构造函数的初始化列表中,构造函数体之前,或者在成员变量声明之后的初始化程序中的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}
{}
Antoher选项是在成员变量声明中提供foo的初始值和 brace-or-equal-initializer :
myClass.hpp
extern "C" {
#include fileWithStruct.h
}
class myClass
{
public:
foo bar{1, 0, "someString", 0x4};
};
在这种情况下,您无需定义构造函数,因为它是由编译器隐式生成的(如果需要),正确初始化bar
。
此处init列表中的聚合初始化不可用,因此您必须使用变通办法,例如:
<强> 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
{ }
答案 2 :(得分:7)
初始化应该以这种方式完成(C ++ 11):
myClass::myClass( )
: bar{1, 0, "someString", 0x4}
{
}
另外,不要忘记在类定义中声明构造函数。
答案 3 :(得分: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;
}
答案 4 :(得分:0)
让我们考虑一个例子。考虑一个链表,其中每个节点都由以下内容表示:
struct ListNode {
int val;
ListNode *next;
ListNode(int x){
val = x;
next = NULL;
}
};
要使用值5和下一个指向NULL的指针初始化节点,您可以将代码段编写为:
ListNode node = new ListNode();
node.val = 5;
node.next = NULL;
或
ListNode node = new ListNode(5);
另一个花哨的声明可以做成
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
这里ListNode(int x): val(x), next(NULL)
是一个构造函数,它初始化struct ListNode的值。
希望这使事情变得更加清晰和容易。 :)