像之前講的,編譯器會將每個.cpp編譯成物件檔.o,最後再用連結器link起來變成exe檔,
那至於怎麼編譯呢,就我理解只要把它想成您編譯的.cpp,裡面有使用到的變數,函式及class,他可以找的到定義,而您的語法又沒問題,就可以編一成一個.o,
我這邊舉一連串的例子來讓您理解,舉個例:
a.cpp
void abc()
{
A b;
}
這個編譯是會出錯的,他會說您沒有定義A,所以您要如何解決咧,就是要在他前面宣告一個實體的struct或class,像這樣
class a{
public:
a(){};
~a(){};
};
void abc()
{
a b;
}
這樣編譯就會過了
要是您的.cpp上方沒有宣告,其實您可以拿到.h中宣告,並include它
a.h
class a{
public:
a(){};
~a(){};
};
a.cpp
#include “a.h”void abc()
{
a b;
}
這樣他就會去include的地方找定義
其實這樣寫法是有問題的,因為通常您程式寫很大時,常常會亂掉,一不小心include太多層,導致同一個.h不小心會include兩次,造成重複定義
所以我們保險起見,有兩種寫法:
1.
舊式a.h
#ifndef A_H
#define A_H
class a
{
public:
a(){};
~a(){};
};
#endif
a.cpp
#include “a.h”
void abc()
{
a b;
}
2.
新式
a.h
class a{
public:
a(){};
~a(){};
};
a.cpp
#pragma once#include “a.h”
void abc()
{
a b;
}
當然也可以兩個都加,因為只不過多個一行,不礙事
這樣就不會發生include多次的問題了(我記得之前的文章有講過原因),
在這邊要注意一件事情,當您在程式中宣告的是一個物件(不管在哪,class或struct),他都會去找他的定義(向上面範例一樣),那要是您宣告的是一個物件指標呢,其實用前置宣告就可以解決了,如下:
註:前置宣告就是向下面紅字一樣,告知編譯器,您這個class存在,在其他地方會實體化
1. 在函式內,
Class a;
void abc()
{
a b;
}
2.
在class內
Class a;Class a
{
Public:
A* b;
}
3. 就任何地方,只要他程式碼往上找找的到就可以(包括寫在標頭檔),像下面這樣也行(還記得之前提的生命週期吧)
Class a
{
Public:
Class a;
A* b;
}
這樣就達到基本的寫法,通常我們在class內定義都會定義指標,不會直接宣告物件,因為會發生我參考網頁上面的那種情況,就是兩個class互相include,因為編譯時互相跳來跳去(連結有寫,我就不打了),導致有定義沒找到,
也就是,您只要照我下面寫法,會比較不會遇到一些Bug:
1. 就是.h有使用到的物件,請宣告成指標,並在前面加上前置宣告(不直接include標頭檔)
2. 在.cpp裡就include您物件定義的標頭檔
3. .h不是實體化任何東西(函式或是class裡的函式),請都移至.cpp定義
a.h
//前置宣告
class b;
class a
{
public:
a();
~a();
Void zzz();
B* a;
};
a.cpp
#pragma once
#include “b.h”
#include “a.h”
A::a()
{}
A::~a()
{}
Void a::zzz()
{A = new b();
Delete A;
}
b.h
//前置宣告class a;
class b
{
public:
b();
~b();
zzz();
a* b
};
b.cpp
#pragma once#include “a.h”
#include “b.h”
b::b()
{}
b::~b()
{}
Void b::zzz()
{A = new b();
Delete A;
}
這樣基本上是我目前寫Code寫得最成功的寫法(目前都這樣寫),真的,不這樣寫Code會卡死,當然還是鼓勵自己試試看錯誤寫法,畢竟您沒看到真的跳出錯誤,您怎麼知道我不是騙您的(笑),程式設計師一開始就摸不會有問題的東西,是不會成長的(要牢記),
八月份就到這裡了,原本沒空弄得(加班加到吐血,還好之前有多打一點)
Blogger還真的很麻煩,排版很累,基本上就看看就好,上班很累,沒時間做得很完美,
12月份應該會按時間貼文章
沒有留言:
張貼留言