本文大面积参考了简书资料 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 <>