2017年3月21日 星期二

兩個 結構、類別 交錯互相使用對方的資源

兩個 結構、類別 交錯互相使用對方的資源

tags: C++ Concept
如何讓兩個 結構、類別 交錯互相使用對方的資源,並拆開定義將檔案拆檔。

完全隱藏類別

使用 inner class 這樣交錯的結構,可以完全隱藏你不想公開的類別
class Fa {
private:
    class Son{
        Son(Fa const &);
    }
    Son data;
};
如果使用 friend 則勢必要將結構公開,你可以使用 private 隱藏,但相對的會佔用一個 class 名稱。

會遇到的問題

如果將定義移動至外面會導致定義不完全出現
field '' has incomplete type ''

資料成員

class Fa {
private:
    class Son;
    Son data;
};

class Fa::Son{

};
因為 Son data; 找不到該目標的實作無法初始化
解決辦法先不要實作利用 指標vector 規避
class Fa {
private:
    class Son;
    vector<Son> data;
    Son* data2;
};

class Fa::Son{

};

副函式

定義副函式的時候也會出現這個問題
class Fa {
private:
    class Son;
    Son fun(size_t pos){}
};

class Fa::Son{

};
返回的數值 Son fun(size_t pos){} 用到了 Son ,一樣找不到該實作的定義。
解決辦法將 fun() 的定義移出至宣告後先不要讓他實做
class Fa {
private:
    class Son;
    Son fun(size_t pos);
};
class Fa::Son{};

Fa::Son Fa::fun(size_t pos){}

可能發生的問題

這裡有一個小坑, Son 必須定義空建構子或是帶有預設數值的引入參數,否則會導致 vector 無法初始化。

示例代碼

未拆開

/*****************************************************************
Name : 類別的互相交錯實作
Date : 2016/12/09
By   : CharlotteHonG
Final: 2017/03/23
*****************************************************************/
#include <iostream>
using namespace std;

struct Fa{
    Fa(string name):name(name){}

    struct Son{
        Son(string name, Fa* fa):name(name), fa(*fa){}
        void fa_name(){
            cout << "My fa = " << this->fa.name << endl;
        }
        string name;
        Fa& fa;
    };

    Son cre_son(string name){
        Son temp(name, this);
        this->son = &temp;
        return temp;
    }

    void son_name(){
        cout << "My son = " << (*son).name << endl;
    }

    string name;
    Son* son;
};

using Son=Fa::Son;
/*=======================================================*/
int main(int argc, char const *argv[]){
    Fa John("John");
    Son Job = John.cre_son("Job");
    // Fa 裡面有 Son , Son 又可以存取 Fa
    Job.fa_name();
    John.son_name();
    return 0;
}
/*=======================================================*/

拆開定義

/*****************************************************************
Name : 類別的互相交錯實作
Date : 2016/12/09
By   : CharlotteHonG
Final: 2017/03/23
*****************************************************************/
#include <iostream>
using namespace std;
// 主類別的宣告
struct Fa{
    Fa(string name):name(name){}

    struct Son;
    Son cre_son(string name);
    void son_name();

    string name;
    Son* son;
}; using Son=Fa::Son;
// 內類別的定義
struct Fa::Son{
    Son(string name, Fa* fa):name(name), fa(*fa){}
    void fa_name();
    string name;
    Fa& fa;
};
// 內類別的函式定義
void Son::fa_name(){
    cout << "My fa = " << this->fa.name << endl;
}
// 主類別的函式定義
Son Fa::cre_son(string name){
    Son temp(name, this);
    this->son = &temp;
    return temp;
}
void Fa::son_name(){
    cout << "My son = " << (*son).name << endl;
}
/*=======================================================*/
int main(int argc, char const *argv[]){
    Fa John("John");
    Son Job = John.cre_son("Job");
    // Fa 裡面有 Son , Son 又可以存取 Fa
    Job.fa_name();
    John.son_name();
    return 0;
}
/*=======================================================*/

沒有留言:

張貼留言