【问题标题】:Compilng different .cpp files with headers使用标头编译不同的 .cpp 文件
【发布时间】:2013-10-28 01:06:23
【问题描述】:

我有问题 我正在尝试使用 GNU g++ 一起编译多个文件

我们假设有五个文件:

main.cpp : the main function 
a.h      : the header file of class A 
a.cpp    : the definition of class A 
b.h      : the header file of class B 
b.cpp    : the definition of class B 

在程序中,main.cpp 使用 A 类(因此包括 a.h),A 类使用 B类(因此包括b.h)。

所以我刚刚添加了#include "a.h"

我正在尝试使用它来编译它

g++ main.cpp -o main

但这不起作用。它给了我一个“未定义的引用”错误。 当我将所有类与头文件一起编译时,该程序为我提供了所需的输出

谁能告诉我哪里出错了

【问题讨论】:

  • 甚至不要思考 #include-将一个 .cpp 文件放入另一个文件中。只是提前告诉你。如果您发现自己认为这是一个好主意,请再想一想。那么请看下面的答案。
  • 没有理由只将一个类放在头文件中。头文件可以(并且通常应该)包含几个相关的声明(类、函数等)和内联函数定义。对于像你这样的小项目,只有一个头文件(你可以预编译)是有意义的。您可以拥有比*.cpp 文件更少的*.h 文件。

标签: c++ header g++


【解决方案1】:

你需要编译所有的源文件:

g++ main.cpp a.cpp b.cpp -o main

如果您想分步进行,您也可以这样做:

g++ -c main.cpp -o main.o  # compile
g++ -c a.cpp -o a.o        # compile
g++ -c b.cpp -o b.o        # compile
g++ -o main main.o a.o b.o # link

但是您应该做的是使用正确的makefile:

CXXFLAGS = -MMD
OBJECTS = main.o a.o b.o
MAKEDEPS = $(OBJECTS:.o=.d)

main: $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $^

clean:
    rm -f *.d *.o main

.PHONY: clean

-include $(MAKEDEPS)

例子:

$ make
c++ -MMD   -c -o main.o main.cpp
c++ -MMD   -c -o a.o a.cpp
c++ -MMD   -c -o b.o b.cpp
c++ -MMD -o main main.o a.o b.o

【讨论】:

  • @user2803194 - 让他们彼此了解
  • 我不确定我是否遵循;标头包含在您的源文件中,对吗?
  • 头文件只包含你的类的声明。所有的实现都在 .cpp 文件中(不一定总是如此)。通过包含头文件,您可以避免 编译器 错误:“未声明变量 abc 和函数 xyz”
  • @user2803194 模块化。标题包含结构和功能规定的声明; .cpp 文件包含后者的实际实现(以及如果在 .cpp 文件之外不需要它们的本地声明)。标头是一个“管道”,一个 .cpp 文件通过它“了解”另一个文件提供的内容,并正确利用该提供。但是实现需要链接在一起才能实现。
  • @CarlNorum:你忘了把-Wall -g 放在你的CXXFLAGS 中(除了-MMD)!
【解决方案2】:

当您只构建main.cpp 时,编译器不会抱怨,因为它会找到您调用的对象和函数的声明。 链接器的工作是确保它可以找到定义。

由于您没有要求编译和链接 a.cppb.cpp 以及 main.cpp,因此您会收到“未定义的引用”错误。

链接器本质上是在告诉您:“嘿,我找不到某某函数的定义。编译器没有抱怨,因为您包含了具有声明的头文件。”

编辑:看到您的评论后,我可以理解您的问题。 声明定义是有区别的。

编译器依赖于查找声明到所使用的类、函数、类型和变量。如果你没有包含头文件(试试看!),你会得到一个来自编译器的Undeclared identifier error

链接器依赖于查找您使用的函数和变量的定义。如果您没有链接包含实现/定义的所需文件,则会收到来自链接器的 Undefined reference to ... 错误。

【讨论】:

    【解决方案3】:

    请阅读http://linux.die.net/man/1/g++

    你需要用 -c 编译然后链接这些对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-28
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多