如何在C++中声明一个结构而不定义它

How can I declare a structure in C++ without defining it?

本文关键字:结构 一个 定义 C++ 声明      更新时间:2023-10-16

我一直在cplusplus.com/doc/tutorial上学习教程。在函数页面的末尾,它讨论了函数的原型设计。后来,我读到了关于结构的文章。我觉得它看起来有点乱,我喜欢我的主方法之后的代码块。所以我想知道我是否可以建立一个数据结构的原型。我试过这个:

#include <iostream>
using namespace std;
struct aStruct;
int main() {
aStruct structure;
structure.a = 1;
structure.b = 2;
cout << structure.a << ", " << structure.b << "n";
return 0;
}
struct aStruct {
int a;
int b;
};

但是我的IDE说"aStruct没有在这个范围内声明">那么,我该如何原型化一个数据结构,使其大部分可以低于主方法

教程页面:功能数据结构

通常,预先声明结构的唯一原因是在定义结构时避免循环引用。正确的解决方案是使用标头,并将结构定义隐藏在标头中:

内部aStruct.h:

#ifndef _ASTRUCT_H
#define _ASTRUCT_H
struct aStruct {
int a;
int b;
};
#endif /* _ASTRUCT_H */

(#ifdefs/等用于防止意外的多重包含,否则会导致错误)内部main.cpp:

#include <iostream>
#include "aStruct.h"
using namespace std;
int main() {
aStruct structure;
structure.a = 1;
structure.b = 2;
cout << structure.a << ", " << structure.b << "n";
return 0;
}

从长远来看,通过将代码正确地组织到单独的文件中,您会更加高兴。

我将把它作为一个练习留给读者,通过使用#ifdef ASTRUCT_H/#define ASTRUCT_H/#endif lines来正确地防止多个标头被包含。

aStruct是一个不完整类型,因此编译器不知道ab是什么。

这种前向声明类型的技巧只能在需要将类型指定为类成员或函数参数时使用。但是,它只适用于指向转发的不完整类型的指针。原因是,如果没有定义,编译器不知道类型的大小,但指针的大小总是相同的。

这里有一个例子。

aStruct.h

struct aStruct
{
int a;
int b;
};

header.h

struct aStruct;
void func(aStruct* ptr);

来源.cpp

#include "header.h" // at this point the compiler only knows of a type aStruct
#include "aStruct.h" // now the compiler has the definition of aStruct
void func(aStruct* ptr)
{
ptr->a = 42;
}

如何在C++中声明一个结构而不定义它?

与您在代码中所做的完全相同。

但是我的IDE说"aStruct没有在这个范围内声明">

这是一个非常令人困惑的诊断。gcc表示"错误:聚合‘aStruct结构’的类型不完整,无法定义"。不能定义不完整类型的对象。

那么,我该如何对数据结构进行原型设计,使其大部分位于主方法之下?

你不能。如果这4行太多,请将定义放入标题中。如果有,可以将成员函数的实现放在main之后,甚至放在另一个编译单元中。就像你可以使用免费功能一样。

关于

我想知道是否可以建立一个数据结构的原型。我试过这个:

#include <iostream>
using namespace std;
struct aStruct;
int main() {
aStruct structure;
structure.a = 1;
structure.b = 2;

不,没有办法“原型";在定义结构之前可以使用其成员的结构。

您可以将结构定义放在main内部或main之前,但无论如何,它必须位于使用成员的代码之前。


如果你不想在编辑器中看到它,那么你可以

  • 使用可以折叠代码区域和/或的编辑器

  • 将定义放入头文件中。


C和C++是为几乎单次编译而设计的,其中通常使用的每个名称都必须已经声明。这包括一个结构的字段。据我所知,这个规则的唯一例外是跳转标签,因为如果没有它们的例外,就需要某种向前声明标签的方式(更复杂),或者必须不支持向前跳转(不受欢迎的限制)。

你可以像在上面的代码中那样转发声明一个结构,但你发现了一个限制:尽管结构名称本身是已知的,并且可以(以有限的方式)使用,但如果没有更完整的定义,你真的无法使用它。完整性的下一个级别是有一个类定义,其规定了结构的构件并因此规定了其尺寸。它足够完整,可以允许所有结构的使用,但要进行代码链接,您还需要所有成员函数的定义,如果这些函数已在类定义中声明但未内联定义–这是完整性的第三个层次,一个完全完整的定义。

根据标准术语,前向声明的结构被称为不完全类型,并且具有已知大小的定义的结构是完整类型

您可以使用类似的正向声明

a结构*结构;

1 #include <iostream>
2 using namespace std;
3 
4 class aStruct;
5 
6 int main() {
7 
8     aStruct *structure ;
9 /*
10     structure->a = 1;
11     structure->b = 2;
12 
13     cout << structure->a << ", " << structure->b << "n";
14 */
15     return 0;
16 }
17 
18 struct aStruct {
19     int a;
20     int b;
21 };

将结构定义放置在int main()之上