这在C ++中给出了错误,但在C:
中没有typedef struct nodes
{
int data;
struct node *next;
}node;
它在C ++中出现以下错误。
/home/DS cpp/linkedlist.cpp|10|error: conflicting declaration ‘typedef struct nodes node’|
/home/DS cpp/linkedlist.cpp|9|error: ‘struct node’ has a previous declaration as ‘struct node’|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
要使它在C ++中工作,我必须将其更改为:
typedef struct node
{
int data;
struct node *next;
}node;
我不明白为什么会这样,我想知道C和C ++中的执行顺序,以便我能理解它。
答案 0 :(得分:25)
让我们稍微分析一下你的代码:
typedef struct nodes
{
int data;
struct node *next;
}node;
这声明并定义struct nodes
,一个包含两个成员的类型,并声明一个类型别名,因此我们只能将其称为node
。
现在,在C ++中,成员声明struct node *next
automatically forward-declares a type called node
。然后会与您的typedef
目标node
发生冲突:就像您尝试为两种类型提供相同的名称一样。
在C中,没有冲突,因为名为node
的类型实际上只能称为struct node
。
第二个片段起作用,因为在解析成员声明struct node
期间已经存在,没有新的类型在那里被前向声明...并且因为你所做的只是在同一个{{1}重命名它语句,C ++并不在乎,知道它们都是相同的类型(typedef
是 struct T
;区别在于语法,而不是名称)。< / p>
T
在给定的非类作用域中,可以使用[C++11: 7.1.3/3]:
说明符重新定义该作用域中声明的任何类型的名称,以引用它已引用的类型。 [例如:typedef
-end example]
typedef struct s { / ... / } s; typedef int I; typedef int I; typedef I I;
在给定范围内,[C++11: 7.1.3/6]:
说明符不得用于重新定义在该范围内声明的任何类型的名称以引用其他类型。 [例如:typedef
-end example]
当然,在C ++中,这一切都没有实际意义,你应该写一下:
class complex { / ... / };
typedef int complex; // error: redefinition
您不需要struct node
{
int data;
node* next;
};
- 远离 elaborated-type-specifier typedef
。
答案 1 :(得分:5)
您提供的C示例应该是错误。您使用的标记名称(node
)尚未使用struct node
定义。
鉴于这两个选择,第二个是使用的选择。我更喜欢经济:
typedef struct node_t
{
int data;
struct node_t *next;
} node_t;
在C或C ++中,标记名称具有自己的名称空间,因此对标记和typedef名称使用相同的名称没有问题。在C中,这允许您使用node_t
或struct node_t
来引用此结构类型。如果声明的类型名称不存在,C ++将在标签名称中搜索类型名称,因此上述双重定义不是必需的,但不会受到伤害。
在两种语言中,在完全定义类型之前的任何时候都需要显式struct node_t
版本,因此任何自引用和任何前向引用都将使用struct
版本。我更喜欢头文件,主要是因为它减少了#include
指令的顺序问题。
PS:这个 可以用任何一种语言工作(参见LRIO对C ++ 11标准指针的回答),并且已经使用了足够的双语甚至是纯C ++头文件。它不太可能很快消失)所以它是一种非常简单的方法,只适用于任何一种语言。