【问题标题】:Symbol clashing of inner and outer structs, C++ vs C内部和外部结构的符号冲突,C++ vs C
【发布时间】:2012-05-17 01:02:07
【问题描述】:

所以,假设我有以下 C++ 标头,testheader.h:

struct mystruct
{
  struct myinnerstruct
  {
        int x;
  } astruct;
};

struct myinnerstruct
{
    int x;
};

以及以下 C++ 源代码,test.cpp:

#include "testheader.h"
using namespace std;
int main()
{
    return 0;
}

g++ 在编译/链接期间没有给出任何问题。

现在,如果我有相同的头文件,但不是 C++ 源代码,而是一个 C 源文件 test.c:

#include "testheader.h"
int main()
{
  return 0;
}

我用 gcc 编译,我得到以下错误:

error: redefinition of struct myinnerstruct

所以,我认为 C 版本的范围是翻译单元,而 C++ 版本是块范围?有人可以确认是这种情况吗,也许给我一个为什么它有意义的理由?我正在混合 C 和 C++ 代码,这给我带来了很多麻烦。

非常感谢任何见解。谢谢!

【问题讨论】:

  • 为什么不直接删除重新定义?
  • @stark :因为它不是重新定义(在 C++ 中),所以它是一个完全不同的类型。
  • @stark 就像重命名内部结构一样?在这个简单的例子中,这是一个明确的解决方案。但我实际使用的代码并不是那么简单,而且我没有那种灵活性,很遗憾。
  • 一个更可爱的方法是在 C++ 程序中包含一个 C 头文件,其内容类似于:typedef struct my_struct { } my_struct;
  • @CrazyEddie - 对不起,我不明白。你能改写或详细说明吗?感谢您的帮助。

标签: c++ c


【解决方案1】:

在 C 中,嵌套结构实际上并不存在于它们的父作用域中。然而,在 C++ 中,它们会 - teststruct::innerstruct 是与 innerstruct 不同的类型。这是为了改进 C++ 代码中的封装。例如,如果没有这条规则,同一个命名空间中的任何两种类型都不能定义嵌套的 iterator 类,这将是非常糟糕的。

C 以许多其他非常愚蠢的方式处理结构,因此他们在这里做错了事也就不足为奇了。但是,C 不允许类型作用域,并且这里有一个健全的规则会为该语言引入许多额外的概念——最终,它需要引入 namespaces,但由于某种原因从未这样做过。

【讨论】:

  • 感谢您的帮助。那么这个奇怪的(IMO)C 范围界定问题仅限于结构吗?这是否解释了为什么我可以在 C main 中声明一个变量 x,然后让 main 调用 myfunc,这也声明了一个变量 x,并且 gcc 很高兴?
  • 如果引入了命名空间,我相信他们也必须在 C 中引入名称修饰,这会导致很多问题。
  • @Jesse:不一定。真正引入名称修饰问题的是模板和重载。单独的命名空间可以很容易地被修改 - 并且具有定义的修改,这根本不会有问题。
【解决方案2】:

在 C 中,内部结构的定义位于外部结构之外,而在 C++ 中则不然。

这已在此博客中解释:Incompatibilities Between ISO C and ISO C++ C 与 C++ 中的许多其他内容,并参考了 C99 和 c++98 ISO 标准。

【讨论】:

  • 感谢您的帮助以及链接。我正在寻找类似的东西。
【解决方案3】:

C 中没有作用域,所以一切都在“全局”命名空间中(用 C++ 语言)

【讨论】:

  • 好吧,那我的下一个问题是,为什么我可以在一个Cmain中声明一个变量x,然后让main调用myfunc,这也声明了一个变量@ 987654325@,一切都好吗?为什么那里没有符号冲突?
  • 因为我们在这里讨论的是类型的范围,而不是变量的范围
【解决方案4】:

在 bot C 和 C++ 中工作的更简洁的方法是:

struct myinnerstruct
{
    int x;
};

struct mystruct
{
  struct myinnerstruct astruct;
};

【讨论】:

  • 只有在 ::myinnerstructmystruct::myinnerstruct 的类型相同时才能在 C++ 中“工作”。
  • 感谢您的提示。问题是我根本无法更改定义甚至任何头文件。
  • @Robᵩ 如果它们不是同一类型,那么无论如何它在 C 中都不起作用。如果没有 C 头文件,则需要用 C++ 编写
猜你喜欢
  • 2020-02-16
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 2012-07-25
相关资源
最近更新 更多