38

所以我想将 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};
}
4

5 回答 5

41

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

括号后面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 风格

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;
};

这里我们使用 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
}

将保留myClass为 POD。

请参阅这篇出色的帖子以了解有关聚合和 POD 的更多信息。

于 2013-06-13T07:00:52.977 回答
11

你在那里做的是分配,而不是初始化。初始化发生在构造函数的初始化列表中,在构造函数主体之前,或者在 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
};

C++11:

我的类.cpp

#include "myClass.hpp"

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

另一个选项是在成员变量声明处为 foo 的初始值提供一个大括号或相等初始化器:

我的类.hpp

extern "C" { 
  #include fileWithStruct.h
}

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

在这种情况下,您不需要定义构造函数,因为它是由编译器隐式生成的(如果需要),正确初始化bar.

C++03:

这里初始化列表中的聚合初始化不可用,因此您必须使用解决方法,例如:

我的类.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
{ }
于 2013-06-13T07:01:04.300 回答
7

初始化应该以这种方式完成(C++11):

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

}

另外,不要忘记在类定义中声明构造函数。

于 2013-06-13T06:58:44.433 回答
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;
}
于 2013-06-13T07:18:53.753 回答
1

让我们考虑一个例子。考虑一个链表,其中每个节点表示为:

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)是一个初始化结构 ListNode 值的构造函数。

希望这能让事情变得更加清晰和容易。:)

于 2019-11-12T13:13:41.973 回答