プライベートコンストラクション関数の役割

5568 ワード

一、背景知識class自体にとって、classオブジェクトとは独立しているため、オブジェクトを生成する必要がなく、classのプライベートドメインを使用することもできるstatic共有メンバーを利用することができる.静的メンバー変数と静的メンバー関数のC++クラスでの役割を参照して理解できます.
二、関連説明コンストラクション関数はclassによって私有化され、オブジェクトを作成する必要がある場合はclassの私有ドメインにアクセスする必要があり、static共有メンバーが行うことができる.static関数でclassのオブジェクトを作成し、参照またはポインタとして返す場合(ここではオブジェクトではなく、主にコンストラクション関数がプライベートであり、外部では一時オブジェクトを作成できません).このオブジェクトの使用権を取得しました.
三、例を挙げて説明する
#include 
using namespace std;

class OnlyHeapClass {
public:
    static OnlyHeapClass* GetInstance()
    {
        cout << "create object,return a pointer" << endl;
        return (new OnlyHeapClass);
    }
    void Destroy() 
    { 
        cout << "delete object" << endl;
        delete this; 
    }
private:
    OnlyHeapClass() {}
    ~OnlyHeapClass() {}
};

void main()
{
    OnlyHeapClass *p = OnlyHeapClass::GetInstance();//         

    p->Destroy();
    return;
}

この例ではプライベートコンストラクション関数を使用し、GetInstance()はOnlyHeapClassの静的メンバー関数としてメモリにオブジェクトを作成します.オブジェクトがスタック上にあるため、GetInstance()が終了してもオブジェクトは解放されず、手動で解放できます.
四、構造関数の私有化の役割構造関数の私有化のクラスの設計は、他のクラスがこのクラスから派生したり、クラスのインスタンスを作成したりすることができないことを保証している.さらに、たとえば、メモリに最大1つまたは複数のオブジェクトが存在するclassを実装したり(classのプライベートドメインにstaticタイプのカウンタを追加したりして、初期値を0に設定してGetInstance()で制限したり、呼び出すたびにカウンタの値がオブジェクト個数の上限値に達しているかどうかを確認し、もしそうであればエラーが発生し、そうでなければnewが新しいオブジェクトを出し、カウンタの値を1つ増やします).最後に、値のコピー時に新しいオブジェクトのコピーが生成されないように、コンストラクション関数をプライベートに設定するほか、レプリケーションコンストラクション関数も特に宣言してプライベートに設定します.コンストラクション関数をProtectedとして設計すれば、同様の目的を達成することもできるが、継承することができる.
五、どのようにオブジェクトを限定してスタックにしか構築できませんか?上記の例では、構造関数をプライベートメンバーとして位置づけ、オブジェクト構築がスタック上でのみ可能であることを限定しています.なぜなら、C++は静的バインディング言語であり、コンパイル中にすべての非虚関数呼び出しが分析され、虚関数であってもアクセス性を確認する必要があるからです.オブジェクトがスタックの上に構築されると、コンパイラによってメモリ領域が割り当てられ、コンストラクション関数が呼び出されてオブジェクトが構築されます.オブジェクトが使用されると、コンパイラは構造関数を呼び出してスタックオブジェクトが占める空間を解放します.
コンパイラは、オブジェクトのライフサイクル全体を管理します.コンパイラがクラスの構造関数を呼び出すことができない場合、すなわち構造関数がプライベートである場合、コンパイラは構造関数を呼び出してメモリを解放できません.したがって、上記の例クラスでは、メモリ領域の解放を行うためにDestroy関数を提供する必要があります.クラスオブジェクトの使用が完了したら、Destroy関数を呼び出す必要があります.
ここで補足すると、delete操作は構造関数を呼び出すので、コンパイルできません.Destroyメンバー関数を提供し、delete操作を完了します.メンバー関数では、構造関数にアクセスできます.もちろんdetele操作もコンパイルできます.
上記の方法の1つの欠点は,継承問題を解決できないことである.OnlyHeapClassが他のクラスのベースクラスである場合、構造関数は通常virtualに設定され、サブクラスで書き換えてマルチステートを実現し、C++マルチステート(一)とC++マルチステート(二)を参照して理解することができる.したがって、構造関数はprivateとは見なされません.洗浄関数をprotectedに設定すると、クラス外ではprotectedメンバーにアクセスできず、サブクラスではアクセスできます.
統一するために、コンストラクション関数をprotectedに設定し、publicのstatic関数を提供してコンストラクションを完了することができ、newを直接使用するのではなく、関数を使用してコンストラクションを構築し、関数を使用してコンストラクションを解析することができます.
#include 
using namespace std;

class A {
public:
    static A* CreateInstance()
    {
        cout << "create object,return a pointer" << endl;
        return (new A);
    }
    void Destroy() 
    { 
        cout << "delete object" << endl;
        delete this; 
    }
protected:
    A() {}
    ~A() {}
};

void main()
{
    A *p = A::CreateInstance();

    p->Destroy();
    return;
}

六、関連問題討論1、どのような場合に自分で構造関数を呼び出す必要がありますか?オブジェクトのライフサイクルが終わると、構造関数を自分で呼び出すのではないでしょうか.なぜ手動で呼び出す必要があるのでしょうか.このような状況を見てみましょう.あなたは構造を分析する前に何かをしなければなりませんが、あなたのクラスの人は知らないので、関数を書き直すことができます.中でやるべきことを全部してから構造関数を呼び出すことができます.このようにして、人はあなたのこの関数を呼び出してオブジェクトを分析するしかなく、それによって分析する前に必ずあなたの要求した動作をすることを保証しました.
2、スタックオブジェクトのみを作成する必要がある場合は?スタックオブジェクトはnewで出てきます.スタックオブジェクトに対して.どのような場合にnewが必要で、どのような場合にスタック内で事前に割り当てられるかは、いつ動的に、いつ静的に生成すべきかの問題にほかならない.これは具体的な状況に応じて具体的に分析しなければならない.たとえば、1つの関数でオブジェクトが最大10個しかないことを事前に知っておくと、このオブジェクトの配列を定義することができます.10個の要素で、各要素はスタックオブジェクトです.数値を特定できない場合は、このオブジェクトのポインタを定義し、作成する必要があるときにnewを出てlistまたはvectorで管理することができます.
3、クラス内の「プライベート」権限の意味は、プライベートメンバーはクラスドメイン内でしかアクセスできず、クラスドメイン外ではアクセスできないということです.構造関数をプライベートとして定義すると,クラスドメイン外での構造関数の使用が阻止される.これは、第1に、ユーザがこのタイプの変数を定義することを禁止すること、すなわち、スタックメモリ空間内でこのタイプのオブジェクトを作成することを禁止することの2つの側面に表れている.オブジェクトを作成するには、newでスタック上でのみ実行できます.第二に、ユーザがプログラム内でdeleteを使用してこのタイプのオブジェクトを削除することを禁止する.オブジェクトの削除はクラス内でのみ実現でき,すなわちクラスの実装者のみがオブジェクトに対するdeleteを実現でき,ユーザは勝手にオブジェクトを削除できない.ユーザがオブジェクトを削除したい場合は,クラスの実装者が提供する方法に従うしかない.このようにすると、ユーザーの使用が大幅に制限されることがわかります.一般的にはそうしないでください.通常は特殊な目的を達成するために使われています.例えば、単例モードの設計では、自分で資料を検索して理解することができます.