2017年5月5日 星期五

如何降低編譯的依存關係

如何降低編譯的依存關係

tags: C++ Concept2

依存關係

依存關係指的是A class的實作必須在寫在B class之前,他們之間存在相依關係,A一定要寫在B之前;或A檔案一定要先被編譯,他們之間不能夠單純依靠宣告來通過編譯。
以下降低解說難易度將檔案縮減至一個單一檔案敘述
假如有一個自訂類別為 Name
// Name class 前置性宣告
class Name;
// Name class 定義 (不是成員函式定義)
class Name{
public:
    Name(string n);
    friend ostream& operator<<(ostream& out, Name const & n);
private:
    string n;
};
那麼要使用這個型別的時候,該class定義必須出現在使用之前
// Name class 宣告
// Name class 定義
Name a("chg");
如果你把class定義移動到下方則會出問題
(Name的函式定義可以移動到下方)
// Name class 宣告
Name a("chg");
// Name class 定義
則會出現相依的問題,產生Name的時候找不到定義;其他class如果要使用Name這個class,會造成Name一定要擺在那之上才可以編譯,如果要交錯互相使用麻煩就大了,誰在上都不對。


Handle Class

解決辦法,可以使用指針來占個位置不把它實作,這樣就不會需要他的實作了
只需要前置性宣告。
// Name class 宣告
Name* a;
// Name class 定義
應用在剛剛說的問題上代碼大概就長這個樣子
// Tw class定義
class Name;
class Tw{
public:
    Tw(string name);
private:
    Name* n;
};
// Name class定義
class Name{
public:
    Name(string n);
    friend ostream& operator<<(ostream& out, Name const & n);
private:
    string n;
};

// Tw建構子
Tw::Tw(string name): n(new Name(name)){
    cout << "n=" << *n << endl;
}
// Name 函式定義
Name::Name(string n): n(n){}
ostream& operator<<(ostream& out, Name const & n){
    out << n.n;
    return out;
}
如此一來順序的相依性就變得兩者皆可(函式的定義也是)
此外這裡的指針也可以使用沒有初始化的vector取代
vector<Name> n;
不要初始化內容
vector<Name> n("name");
也不要初始化長度
vector<Name> n(1);
反例中的代碼因為Name沒有預設建構子(引數可為無的建構子),僅能使用 push_back() 初始化
// Tw建構子
Tw::Tw(string name){
    n.push_back(name);
    cout << "n=" << n[0] << endl;
}


Protocol Class

利用虛擬函式的特性,不需要先做,藉此避開宣告時必須要要定義的狀況。
// Name class 宣告
// 純虛擬類別定義(抽象類別宣告內含Name)

// Name class 定義
// 繼承抽象類別


參考代碼

Handle Class
/*****************************************************************
Name : Handle Class
Date : 2017/05/04
By   : CharlotteHonG
Final: 2017/05/04
*****************************************************************/
#include <iostream>
#include <string>
#include <vector>
using namespace std;

// Tw class定義
class Name;
class Tw{
public:
    Tw(string name);
private:
    Name* n;
    // vector<Name> n;
};

//================================================================
int main(int argc, char const *argv[]){
    Tw a("chg");
    return 0;
}
//================================================================

// Name class定義
class Name{
public:
    Name(string n);
    friend ostream& operator<<(ostream& out, Name const & n);
private:
    string n;
};
// Tw建構子
Tw::Tw(string name){
    n = new Name(name);   // point
    // n.push_back(name); // vector
    cout << "n=" << n[0] << endl;
}
// Name 函式定義
Name::Name(string n): n(n){}
ostream& operator<<(ostream& out, Name const & n){
    out << n.n;
    return out;
}
Protocol Class
/*****************************************************************
Name :
Date : 2017/05/04
By   : CharlotteHonG
Final: 2017/05/05
*****************************************************************/
#include <iostream>
using namespace std;
// Tw class定義
class Name;
class Tw{
public:
    virtual ~Tw(){}
    virtual string name()=0;
    static Tw* makeTw(Name const & name);
};

// Name class定義
class Name{
public:
    Name(string const & n);
    operator string&(){
        return n;
    }
    friend ostream& operator<<(ostream& out, Name const & n);
private:
    string n;
};
//================================================================
int main(int argc, char const *argv[]){
    Tw* p;
    Name chg = string("chg");
    p = Tw::makeTw(chg);
    cout << p->name() << endl;
    return 0;
}
//================================================================

// Tw class定義
class RealTw: public Tw{
public:
    RealTw(Name const & name): n(name){}
    string name(){return n;}
private:
    Name n;
};

// makeTw 函式定義
Tw* Tw::makeTw(Name const & name){
    return new RealTw(name);
}

// Name 函式定義
Name::Name(string const & n): n(n){}
ostream& operator<<(ostream& out, Name const & n){
    out << n.n;
    return out;
}

沒有留言:

張貼留言