将函数参数更改为 const 时 Makefile 不起作用
Makefile not working when changing function argument to const
我在使用 makefile 编译 C++ 代码时遇到了一个奇怪的问题。代码首先编译完美。然后我将一个函数参数更改为 "const"。如果我随后编译,当代码尝试使用我将参数更改为 const 的函数时,我将收到错误消息。这可以通过删除所有 .o 文件然后再次编译来解决,但我很好奇首先导致此问题的原因。我的文件是:
MyClass.h
class MyClass {
public:
void fun(double*const c);
};
MyClass.cpp
#include "MyClass.h"
void MyClass::fun(double *const c){
};
Main.cpp
#include "MyClass.h"
int main(int argc,char* argv[]) {
MyClass foo;
double *bar=new double[2];
foo.fun(bar);
};
生成文件
all: main
main: Main.o MyClass.o
g++ -o a.out Main.o MyClass.o
Main.o: Main.cpp
g++ -c Main.cpp
MyClass.o: MyClass.cpp
g++ -c MyClass.cpp
如果我现在先 运行 make
,一切正常。但是后来我将 fun
的签名更改为 fun(const double *const c)
,我收到错误消息
Main.cpp:(.text+0x3b): undefined reference to `MyClass::fun(double*)'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1
但是,如果我删除所有 .o 文件,然后再次 运行 make
,它会编译。
规则
main.o: Main.cpp
说 main.o
目标文件只依赖于 Main.cpp
源文件。 但是它实际上依赖于另一个文件:MyClass.h
头文件。
目标名称的大小写也有错误。
以上两个问题的意思是当你更改头文件MyClass.h
更新函数签名时,Main.o
目标文件不会被重新创建并且仍然引用旧函数
所以规则应该是
Main.o: Main.cpp MyClass.h
该添加将导致 Main.o
目标文件在您更改头文件时重新编译。
MyClass.o
目标也应进行此更改。
另请注意,main
目标使用 MyClass.o
作为依赖项,但随后您在链接时使用 MyClass.cpp
source 文件,而不是目标文件。
目标的名称也应该是生成文件的名称(即在您的情况下为 a.out
)。
问题是,您的 Makefile 已损坏:它忽略了一个事实,即 .o
文件不仅依赖于相应的 .cpp
文件,而且还依赖于 .h
它包含的文件。正确的 Makefile 规则必须包含 所有 依赖项,包括直接甚至间接包含的 .h
个文件。
因为你的 Makefile 是不完整的,make
当它的定义改变时没有重新编译你的函数的调用点,所以陈旧的对象仍然引用非常量函数。由于 C++ 名称改组,链接器在行为中捕获了它,错误在 C 中不会被注意到!
要彻底解决这种情况,我建议您花一两个小时阅读这篇文章 article on automatic dependency generation,并在您的 Makefile 中实施它提供的一些解决方案。完成此操作后,您可能只需将现有解决方案复制到未来项目的 Makefile 中,否则就会忘记这个问题。
我在使用 makefile 编译 C++ 代码时遇到了一个奇怪的问题。代码首先编译完美。然后我将一个函数参数更改为 "const"。如果我随后编译,当代码尝试使用我将参数更改为 const 的函数时,我将收到错误消息。这可以通过删除所有 .o 文件然后再次编译来解决,但我很好奇首先导致此问题的原因。我的文件是:
MyClass.h
class MyClass {
public:
void fun(double*const c);
};
MyClass.cpp
#include "MyClass.h"
void MyClass::fun(double *const c){
};
Main.cpp
#include "MyClass.h"
int main(int argc,char* argv[]) {
MyClass foo;
double *bar=new double[2];
foo.fun(bar);
};
生成文件
all: main
main: Main.o MyClass.o
g++ -o a.out Main.o MyClass.o
Main.o: Main.cpp
g++ -c Main.cpp
MyClass.o: MyClass.cpp
g++ -c MyClass.cpp
如果我现在先 运行 make
,一切正常。但是后来我将 fun
的签名更改为 fun(const double *const c)
,我收到错误消息
Main.cpp:(.text+0x3b): undefined reference to `MyClass::fun(double*)'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1
但是,如果我删除所有 .o 文件,然后再次 运行 make
,它会编译。
规则
main.o: Main.cpp
说 main.o
目标文件只依赖于 Main.cpp
源文件。 但是它实际上依赖于另一个文件:MyClass.h
头文件。
目标名称的大小写也有错误。
以上两个问题的意思是当你更改头文件MyClass.h
更新函数签名时,Main.o
目标文件不会被重新创建并且仍然引用旧函数
所以规则应该是
Main.o: Main.cpp MyClass.h
该添加将导致 Main.o
目标文件在您更改头文件时重新编译。
MyClass.o
目标也应进行此更改。
另请注意,main
目标使用 MyClass.o
作为依赖项,但随后您在链接时使用 MyClass.cpp
source 文件,而不是目标文件。
目标的名称也应该是生成文件的名称(即在您的情况下为 a.out
)。
问题是,您的 Makefile 已损坏:它忽略了一个事实,即 .o
文件不仅依赖于相应的 .cpp
文件,而且还依赖于 .h
它包含的文件。正确的 Makefile 规则必须包含 所有 依赖项,包括直接甚至间接包含的 .h
个文件。
因为你的 Makefile 是不完整的,make
当它的定义改变时没有重新编译你的函数的调用点,所以陈旧的对象仍然引用非常量函数。由于 C++ 名称改组,链接器在行为中捕获了它,错误在 C 中不会被注意到!
要彻底解决这种情况,我建议您花一两个小时阅读这篇文章 article on automatic dependency generation,并在您的 Makefile 中实施它提供的一些解决方案。完成此操作后,您可能只需将现有解决方案复制到未来项目的 Makefile 中,否则就会忘记这个问题。