【C++从入门到放弃】C++/g++不同文件夹的编译

本文大面积参考了简书资料 https://www.jianshu.com/p/2b047bcce8fa ,由于源书上存在好几处细节上的问题,比如:

class Afunc   应该是   class A
std::cout<<#include "A()"<<std::endl;    应该是  std::cout<<"#include A()"<<std::endl; 

等等,会产生一些误导,特重新整理了一版

测试环境

g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

可能遇到的错误

可能遇到的错误,专门列出来,以备工作中遇到类似错误知道是什么原因造成的

./A.h:13:5: error: C++ requires a type specifier for all declarations
    A();
    ^
mainA.cpp:9:5: error: use of undeclared identifier 'A'; did you mean 'Afunc::A'?
    A a;
    ^
    Afunc::A
./A.h:13:5: note: 'Afunc::A' declared here
    A();
    ^
mainA.cpp:9:5: error: call to non-static member function without an object argument
    A a;
    ^


Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-9d0067.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]

mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
A.cpp:6:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"
1 error generated.
mingyuedeMacBook-Pro:cstudy3 mac$ 
mingyuedeMacBook-Pro:cstudy3 mac$ 
mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp
A.cpp:6:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"


相同文件夹单文件

include "A.h"引入

在A文件夹里有A.h,A.cc,mainA.cc三个文件,代码及目录如下:

目录

 tree
.
├── A.cpp
├── A.h
└── mainA.cpp

0 directories, 3 files

A.h内容

 more A.h 

#ifndef CSTUDY3_A_H
#define CSTUDY3_A_H

#include <iostream>
class A
{
public:
    A();
};

#endif //CSTUDY3_A_H

## A.cpp内容
 more A.cpp 

#include "A.h"

A::A()
{
    std::cout<<"#include A() hahaa 888"<<std::endl;
}

mainA.cpp内容

 more mainA.cpp 

#include "A.h"     

int main()
{
    A a;
    return 0;
}

编译指令

g++ mainA.cpp 和 g++ mainA.cpp A.h 均会报错

 g++ mainA.cpp 
Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-9d7e58.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
 
 g++ mainA.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-cfb0dc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

大致意思就是 mainA-*.o文件中没有找到以A:A()的实现。
后面的指令也也同样提示,也就说明,g++并不会根据A.h文件,自动去找它的实现A.cpp。

而这两条命令相同,说明include " "引入的文件,会在当前目录搜索,并自动加入。

正确的编译命令为 g++ mainA.cpp A.cpp 或 g++ mainA.cpp A.cpp A.h

 g++ mainA.cpp A.cpp
 g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
mingyuedeMacBook-Pro:A mac$ 

其中g++ mainA.cpp A.cpp A.h执行时会有waring,但是可以正常编译通过
说明,A.h的实现文件A.cpp需要显式说明,而A.h可以不用明确写出。

include <A.h>引入

上面的目录结构不变,将mainA.cpp中的#inlcude "A.h"改为#include <A.h>

编译指令

g++ mainA.cpp A.cpp 会报错

$ g++ mainA.cpp A.cpp
mainA.cpp:1:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
        ^~~~~
        "A.h"
1 error generated.

说明include <>引入的文件,并不在当前目录搜索,只会在系统制定的目录搜索

正确的编译命令 g++ mainA.cpp A.cpp -I./

g++ -I参数

-I可以将include <>原本的搜索目录进行扩展。
上面的语句表示将./也就是当前目录加入到其搜索目录中。至于搜索顺序,后面讨论。。
如果同时将A.cc中的include “ ”也更改,那么结果时相同的。
至于应该使用哪种方式引入,实现文件,使用哪种方式。还没找到资料。
看过别人的库,是使用的include <>引入的。

不同文件夹单文件

include "A/A.h"引入

将上面的mainA.cc文件,移出A文件夹,和A文件夹放在同一级。

 tree
.
├── A
│   ├── A.cpp
│   └── A.h
└── mainA.cpp

修改mainA.cpp文件include部分(因为mainA.cpp已经与A.h不在同一个文件夹下了)


 more mainA.cpp 
#include "A/A.h"

int main()
{
    A a;
    return 0;
}

用刚才正确的编译命令g++ mainA.cpp A.cpp试一把,报错

 g++ mainA.cpp A.cpp 
clang: error: no such file or directory: 'A.cpp'

此时正确的编译命令为:g++ mainA.cpp A/A.cpp

题外话:cpp文件中必须采用既在include " "中标明相对路径,另外编译指令中也需要标明相对路径

include <A/A.h>引入

修改mainA.cpp文件include部分(改成include <A/A.h>)

 more mainA.cpp 
#include <A/A.h>

int main()
{
    A a;
    return 0;
}

用户刚才的编译命令会报错

 g++ mainA.cpp A/A.cpp 
mainA.cpp:1:10: error: 'A/A.h' file not found with <angled> include; use "quotes" instead
#include <A/A.h>
         ^~~~~~~
         "A/A.h"
1 error generated.

此时正确的编译命令为:g++ mainA.cpp A/A.cpp -I.

如果我们进一步修改A/A.cpp文件中的include部分呢

 more A/A.cpp 
#include <A.h>

A::A()
{
    std::cout<<"#include A() hahaa 444"<<std::endl;
}

用户刚才的编译命令会报错

 g++ mainA.cpp A/A.cpp -I.
A/A.cpp:1:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"
1 error generated.

错误原因大概就是需要增加目录./A/ 作为搜索的目录之一

此时正确的编译命令为:g++ mainA.cpp A/A.cpp -I. -I./A/

不同文件夹多文件

在目录A中增加子目录C,及文件C.h C.cpp

 tree
.
├── A
│   ├── A.cpp
│   ├── A.h
│   └── C
│       ├── C.cpp
│       └── C.h
├── a.out
└── mainA.cpp

 more A/C/C.h 
#ifndef CSTUDY3_C_H
#define CSTUDY3_C_H

#include <iostream>
class C {
public:
    C();
};

#endif //CSTUDY3_C_H

 more A/C/C.cpp 
#include "C.h"

C::C() {
    std::cout << "C()" << std::endl;
}

刚才的编译命令可以编译通过
g++ mainA.cpp A/A.cpp -I. -I./A/

说明:尽管新增了文件夹及cpp文件,只要mainA.cpp中没有引用,就不用管

修改mainA.cpp文件如下:

#include <A/A.h>
#include <A/C/C.h>

int main()
{
    A a;
    C c;
    return 0;
}

再次执行上面的编译命令就会报错

  g++ mainA.cpp A/A.cpp -I. -I./A/
Undefined symbols for architecture x86_64:
  "C::C()", referenced from:
      _main in mainA-d53a4c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

正确的编译命令为:

 g++ mainA.cpp A/A.cpp A/C/C.cpp  -I. -I./A/

说明:这里没有加 -I./A/C/ 也是可以的,这是由于A/C/C.cpp中include采用的是#include “” 方式,而不是#include <>

发布了100 篇原创文章 · 获赞 64 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/hl_java/article/details/90766721