本文大面積參考了簡書資料 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 <>