我同意 Csaba Toth 在评论中的观点。这是一团糟,您应该正确清洁它。说服那些让你参与项目的人,花时间用适当的头文件和源文件重写它是值得的。它将为他们节省大量的开发和支持,并有助于在客户发现之前发现错误。
也就是说,您仍然需要处理外部问题。
你的选择1很差。.cpp 不应包含另一个 .cpp。您没有收到大量“已定义”错误,这简直是奇迹。
选择 2 在文件 B 中定义另一个静态 int。这将是与文件 C 中的不同的 int,它们可以有不同的值。
您需要做的是将文件 C 的 int 声明为extern
. 您可以在标头或 cpp 中执行此操作。诀窍是确保它只在一个地方实例化。
所以,在 B 的某些部分,这样做:
extern int dog;
dog
这告诉编译器在程序准备好运行时将调用一个 int 。然后,链接器将查找该变量的唯一一个实例——当前位于 fileC.cpp 中——并将所有内容指向同一个位置。
您的选择 3 给您带来了问题,因为您有两个同名的全局范围变量。使用extern
将解决这个问题。
一般来说,好的编码结构应该是:
头文件
- 确保有包装器,
#ifdef MYFILE_H
或者#pragma once
如果它受支持,以确保 .h 永远不会被包含超过一次。
- 只放置函数声明 - 你应该有很少的实现,除非你不顾一切地让它内联(现在好的编译器可以在大多数情况下自行优化)。您应该确保您实现的任何功能仅在该文件内部,并且不依赖于其他文件。
- 您可以使用
extern
.
Cpp 文件
最干净的事情是匹配头文件中的实现,尽管编译器和链接器可以让你在任何地方实现任何东西。要遵循的主要规则是每个函数和每个外部函数在所有代码中只实现一次。应该只有一个地方有函数myFunc
,并且应该只有一个地方声明int dog
而不是extern int dog
. 函数声明和extern
变量都告诉编译器“别担心,我会确保它完成的”,然后链接器在所有对象中查找它。
我猜,从你没有在你的选择 1 和选择 2 中提到任何错误的事实,你得到了编译,但从未运行过链接器。我的下一个猜测是这是一个 unix 系统,因为 Visual Studio 会同时处理这两个步骤。在那种情况下,必须有一些make
系统来负责构建,或者其他什么。您应该在所有三个选择中都有错误。