C++ 在类构造函数中初始化结构的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17080975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct way of initializing a struct in a class constructor
提问by tzippy
So I want to add a struct from a c header file as a class member to a c++ class.
But I get a compiler error for the cpp
file: bar was not declared inn this scope
.
This is what I have:
所以我想将ac头文件中的结构作为类成员添加到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};
}
回答by legends2k
C++03 Style
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()
{
}
};
The parentheses following bar
matters. Refer value and zero-initializationto understand why this works. It is to be noted that by adding a constructor to myClass
, we've made it a non-POD type. To work around this, one can retain myClass
as an aggregate and write:
在后面的括号bar
事项。请参阅值和零初始化以了解其工作原理。需要注意的是,通过向 中添加构造函数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 Style
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) : val{}, bar{_foo1, 0.f}
{
}
// 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;
};
Here we use C++11's uniform initialization syntax. However, by doing this myClass
becomes a non-POD type; member initialization is akin to adding a constructor to the class, thereby rendering myClass
a non-trivial but standard-layout class. As per C++11 for a class to be POD it should be both trivial and standard-layout. Instead doing
这里我们使用 C++11 的统一初始化语法。但是,这样做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
}
will retain myClass
as a POD.
将保留myClass
为 POD。
Refer to this excellent postto know more about aggregates and PODs.
请参阅这篇优秀的文章以了解有关聚合和 POD 的更多信息。
回答by Arne Mertz
What you are doing there is assignment, not initialization. Initialization happens in the initialization list of a constructor, before the constructor body, or in C++11 in an initializer right after the member variable declaration:
你在那里做的是赋值,而不是初始化。初始化发生在构造函数的初始化列表中,在构造函数体之前,或在 C++11 中的成员变量声明之后的初始化程序中:
myClass.hpp, general case:
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
我的类.cpp
#include "myClass.hpp"
//Initialize structure in Constrcutor
myClass::myClass( )
: bar{1, 0, "someString", 0x4}
{}
Antoher option is to provide the initial value of foo with an brace-or-equal-initializerat the member variable declaration:
另一个选项是在成员变量声明中使用大括号或等号初始值设定项提供 foo 的初始值:
myClass.hpp
我的类.hpp
extern "C" {
#include fileWithStruct.h
}
class myClass
{
public:
foo bar{1, 0, "someString", 0x4};
};
In this case, you need not define a constructor, since it's generated implicitly by the compiler (if needed), correctly initializing bar
.
在这种情况下,您不需要定义构造函数,因为它是由编译器(如果需要)隐式生成的,正确初始化bar
.
C++03:
C++03:
Here aggregate initialization in init lists is not available, so you have to use workarounds, e.g.:
这里 init 列表中的聚合初始化不可用,因此您必须使用解决方法,例如:
myClass.cpp
我的类.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;
}
Or:
或者:
#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
{ }
回答by Matthieu Rouget
Initialization should be done this way (C++11):
初始化应该这样完成(C++11):
myClass::myClass( )
: bar{1, 0, "someString", 0x4}
{
}
Also, do not forget to declare your constructor in your class definition.
另外,不要忘记在类定义中声明构造函数。
回答by tarjeik
You need to specify that the foo struct should have "C-linkage". The following is a complete example.
您需要指定 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
The myClass header file:
myClass 头文件:
// myClass.hpp
#include "fileWithStruct.h"
class myClass
{
public:
myClass();
foo bar;
};
The C+11 implementation of myClass which uses extended initializer lists:
使用扩展初始化列表的 myClass 的 C+11 实现:
// myClass.cpp
#include "myClass.hpp"
myClass::myClass( )
: bar({1, 0, "someString", 0x4})
{
}
... and the C++03 version if you haven't moved to C++11 yet:
...以及 C++03 版本(如果您还没有迁移到 C++11):
#include "myClass.hpp"
myClass::myClass( )
: bar()
{
bar.a = 1;
bar.b = 0;
bar.c = "someString";
bar.d = 0x4;
}
回答by sarthakgupta072
Let us consider an example. Consider a Linked List in which each node is represented by:
让我们考虑一个例子。考虑一个链表,其中每个节点表示为:
struct ListNode {
int val;
ListNode *next;
ListNode(int x){
val = x;
next = NULL;
}
};
To initialize a node with value 5 and next pointer pointing to NULLyou can write the code snippet as:
要使用值 5 和指向 NULL 的下一个指针初始化节点,您可以将代码片段编写为:
ListNode node = new ListNode();
node.val = 5;
node.next = NULL;
or
或者
ListNode node = new ListNode(5);
Another fancy declaration can be made as
另一个花哨的声明可以作为
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
Here ListNode(int x): val(x), next(NULL)
is a constructor which initializes the value of the struct ListNode.
这ListNode(int x): val(x), next(NULL)
是一个构造函数,它初始化结构 ListNode 的值。
Hope this make things more clear and easy. :)
希望这能让事情变得更加清晰和容易。:)