C++(十)構造関数と構造関数

27726 ワード

文書ディレクトリ
  • 一、構造関数
  • 1.1コンストラクション関数を使用してオブジェクト
  • を初期化する.
  • 1.2パラメータ付き構造関数:
  • 1.3関数のリロード
  • 1.4デフォルトパラメータ
  • 1.5コンストラクタのパラメータ初期化テーブル
  • 1.6構造関数の4つの方式

  • 二、構造関数
  • 2.1構造関数の役割
  • 2.2文章全体の小例:




  • 一、構造関数
    通常、int a=0という変数を定義して初期化します.これにより、この変数は使用時に初期値、すなわち初期化されます.私たちはクラス(オブジェクト)を定義するときも、それを初期化する必要があります.クラスは構造体から発展してきたので、以前の構造体の初期化操作は、クラスがサポートしていました.定義するときに直接初期化してもいいし、定義してから初期化してもいいです.
    あるいは、オブジェクト定義が終わったらすぐに初期化したいと思います.この初期化は、クラスのメンバーに初期値を付与し、変数をデフォルトで乱雑で規則的な初期化されていない状態の数にしたくないと言えます.私たちはこのようにすることができます.
    class student
    {
         
    public:
    	int num;
    	char *name;
    	char sex;
    	float score;
    };
    
    int main()
    {
         
    	student stu_01[3] = {
         
    		{
          101,"Zhou ping",'M',45 },
    		{
          102,"Zhang ping",'M',62 },
    		{
          103,"Liou fang",'F',92.1 },
    	};
    	return 0;
    }
    

    前の例では、オブジェクト配列の各値に初期値を割り当てましたが、未知数があればループで行いますか?とても面倒で、しかも、あなたのこのような初期化の方式はpublicタイプのメンバーを初期化するしかなくて、privateタイプのあなたは初期化できません.そこで構造関数を引き出した.
    コンストラクション関数:オブジェクトの初期化を解決するために使用されます.コンストラクション関数は特殊なメンバー関数で、他のメンバー関数とは異なり、ユーザーがアクティブに呼び出す必要はありません.コンストラクション関数はオブジェクトが確立されたときに自動的に呼び出されます.オブジェクトを処理するための初期化操作です.
    注意事項:
    ①、コンストラクタの名前はクラス名と同名でなければならず、勝手に名前をつけることができない.そうすれば、コンパイラにクラスの普通のメンバー関数ではなく、コンストラクタがコンストラクタであると見なされる.
    ②、コンストラクション関数はいかなるタイプも持たず、いかなる値も返さず、voidでもない.
    ③、コンストラクション関数は必要もなく、ユーザーに呼び出されるべきではなく、オブジェクトが確立されたときに自動的にシステムに呼び出され、確立されたばかりのオブジェクトを初期化するために使用される.
    ④、ユーザーが自分のクラスのコンストラクション関数を定義していない場合、システムは自動的にデフォルトのコンストラクション関数を生成しますが、そのコンストラクション関数の関数体は空で、つまり何もしません.
    1.1コンストラクション関数を使用したオブジェクトの初期化
    例:
    #include
    #include 
    using namespace std;
    
    class CStudent
    {
         
    public:
    	CStudent()    //            
    	{
         
    		name = "";
    		num = 0;
    		sex = 'm';
    	}
    	void set_info();
    	void print_info();
    private:
    	string name;
    	char sex;
    	int num;
    };
    
    void CStudent::set_info()
    {
         
    	cout << "     :  ;  ;  :" << endl;
    	cin >> name;
    	cin >> num;
    	cin >> sex;
    }
    
    void CStudent::print_info()
    {
         
    	cout << "name=>sex=>num:" << endl;
    	cout << name << ";" << sex << ";" << num << endl;
    }
    
    int main()
    {
         
    	CStudent stu1;
    	stu1.set_info();
    	stu1.print_info();
    	return 0;
    }
    ==========================
         :  ;  ;  :
    zhangsan
    123
    m
    name=>sex=>num:
    zhangsan;m;123
    

    1.2パラメータ付きコンストラクション関数:
    Studentクラスは、デフォルトのパラメータを持たないコンストラクション関数を提供するだけでなく、クラスオブジェクトを定義する際に自動的に呼び出すことができるようにするもよいし、パラメータ付きコンストラクション関数を提供してもよいかどうか、クラスオブジェクトを定義する際にコンストラクション関数のパラメータを利用してオブジェクトのメンバーを初期化することができる.
    1.3関数のリロード
    通常のプログラミングの過程で、1つの関数は1つの機能を実現することができて、複数の機能は複数の関数を必要とします.しかし、複数の機能の間に似ている場合がありますが、いくつかの細部に違いがある場合、このような機能は関数として書きたいと思っています.例えば、与えられた数の中で最大の数:int max(int a, int b); float max(float a, float b, float c);上の2行のコードがリロードであることが要求される.
    関数リロードの要件(関数フィーチャーラベルが異なる):リロード関数のパラメータ個数、パラメータタイプ、パラメータ順序の3つのうち少なくとも1つが異なる必要があります(そうでないと呼び出し疑惑が発生します).関数の戻り値タイプは同じでも異なってもよい.単純に戻り値タイプが異なる2つの同名関数は関数リロードを構成することができず、リンクエラーが報告されます.
    1.4デフォルトパラメータ
    関数のデフォルトパラメータの注意事項:1、関数宣言の時に指定し、関数の宣言がなければ関数の定義に置くことができますが、宣言と定義は1つしか選択できません.②、最初のデフォルト値のあるパラメータから、後のすべてのパラメータにデフォルト値がある必要があります.(pythonもそうです)③、呼び出すときに最初のデフォルト値以外のパラメータをカスタマイズする場合は、前のすべてのパラメータにデフォルト値を明確に記入する必要があります;(pythonもそうです)④、使用角度から言えば関数のデフォルト値はリロードよりも便利で、関数の内部実装角度から言えば関数のリロードよりも複雑です.
    1.5コンストラクション関数のパラメータ初期化テーブル
    このように実現される構造関数は体積が小さく,コードがより簡潔に見える.
    //         
    class CStudent
    {
         
    public:
        char name[50];
        char sex;
        int num;
        int age;
    
        CStudent(char* pname, char t_sex, int t_num, int t_age);
    };
    
    //            
    CStudent::CStudent(char* pname, char t_sex, int t_num, int t_age) :sex(t_sex), num(t_num), age(t_age)
    {
         
        strcpy(name, pname);
    }
    

    1.6コンストラクション関数の4つの方法
  • デフォルトのコンストラクション関数.Studentクラスを例にとると、デフォルトのコンストラクタのプロトタイプはStudent()です.//パラメータなし
  • 初期化構造関数Student(int num,int age);//パラメータ
  • あり
  • 複製(コピー)コンストラクション関数Student(Student&);//パラメータは、このクラスのオブジェクトの参照オブジェクトを関数パラメータとして、値伝達の方法で関数体に伝達します.オブジェクトは関数として値伝達の方法で関数から戻ります.オブジェクトは他のオブジェクトを初期化するために使用されます.(通常は付与初期化と呼ばれる)、1つのオブジェクトを直接使用して別のオブジェクトを初期化するには、演算子を再ロードする必要があります.そうしないと、解析時に
  • とエラーが発生しやすくなります.
  • 変換構造関数Student(int r);//パラメトリックは他のタイプの変数であり、1つのパラメトリックのみが、1つのコンストラクション関数に1つのパラメータしかなく、このパラメータがクラスのconst参照ではない場合、このコンストラクション関数を変換コンストラクション関数と呼び、暗黙的にクラスオブジェクトに変換します.

  • 二、構造関数
    構造関数もクラス内で構造関数に似た特殊な機能のメンバー関数です.ただし、コンストラクション関数とは逆に、オブジェクトのライフサイクルが終了すると自動的に呼び出されます.構造関数の名前はクラス名と同じで、前に逆の記号~が付いていて、表現の意味は構造関数の過程とは逆です.
    デフォルトでは、クラスの設計者が自分で構造関数を定義していない場合、コンパイラは自動的にクラスのデフォルトの構造関数を生成します.ただし、関数体は空で、つまり何もしていません.したがって、オブジェクトが削除されるときにいくつかの操作を行う必要がある場合は、構造関数を自分で定義する必要があります.
    以下の場合、構造関数が自動的に呼び出されます.
    ①、1つの関数にローカル変数のオブジェクトが定義されている場合、この関数の実行が終了すると、その変数オブジェクトのライフサイクルが終了するので、構造関数が自動的に呼び出されます.
    ②、グローバル変数またはstaticタイプの変数.彼らのライフサイクルは一般的にプログラムが終了したときに、そのオブジェクトの構造関数が呼び出される.
    ③、newオペレータで動的にオブジェクトを作成した場合、deleteでオブジェクトを解放した場合にのみ、構造関数が呼び出されます.
    2.1構造関数の役割
    コンストラクション関数は、新しいオブジェクトではなく、オブジェクトが作成された後に自動的に呼び出され、関連情報を初期化するための関数です.同様に、構造関数もオブジェクトを削除するために使用されるのではなく、オブジェクトが削除されると自動的に呼び出され、一部のオブジェクトが削除される前のクリーンアップ作業に使用されます.オブジェクトのライフサイクルが終了すると、プログラムは自動的に構造関数を実行してこの作業を完了します.構造関数は値を返さず、関数タイプも関数のパラメータも返されません.これらの特徴により,構造関数は再ロードできないため,1つのクラスに複数の構造関数を持つことができるが,1つの構造関数しか持たない.
    2.2文章全体の小例:
  • ヘッダファイル、宣言(クラス、コンストラクション関数、コンストラクション関数)
  • #pragma once
    #pragma warning(disable:4996)
    #include 
    using namespace std;
    
    class C_Student
    {
         
    private:
    	char * name;
    	int len;
    	static int num_strings;
    
    public:
    	C_Student();
    	C_Student(const char * s);
    	~C_Student();
    
    	friend ostream & operator << (ostream & os, const C_Student & st);
    };
    
  • 実装関数(関数の具体的な実装)
  • // gouzao_hanshu_01.cpp :              。
    //
    #pragma warning(disable:4996)
    #include "stdafx.h"
    #include 
    #include "Student_h.h"
    using namespace std;
    
    int C_Student::num_strings = 0;
    
    
    C_Student::C_Student()
    {
         
    	len = 10;
    	name = new char[10];
    	strcpy(name, "zhang");
    	num_strings++;
    	cout << "num_string_null:" << num_strings << endl;
    }
    
    
    C_Student::C_Student(const char * s)
    {
         
    	len = strlen(s);
    	name = new char[len + 1];
    	strcpy(name, s);
    	num_strings++;
    	cout << "num_string_dong:" << num_strings << endl;
    }
    
    
    C_Student::~C_Student()
    {
         
    	--num_strings;
    	delete [] name;         //  new []     ,    delete []     
    	cout << "      :" << num_strings << endl;
    }
    
    ostream & operator << (ostream & os, const C_Student & st)
    {
         
    	os << st.name;
    	return os;
    }
    
  • 主関数(インスタンス化オブジェクト)
  • #pragma warning(disable:4996)
    #include "stdafx.h"
    #include 
    #include 
    #include "Student_h.h"
    using namespace std;
    
    
    
    
    int main()
    {
         
    	cout << "======   :======" << endl;
    	C_Student stu01("wawawa");
    	C_Student stu02("hahaha");
    	cout << "======stu01    :======" << stu01 << endl;
    	cout << "======stu02    :======" << stu02 << endl;
    	return 0;
    }
    
    
    ====================    =====================
    ============
    num_string_dong:1
    num_string_dong:2
    ======stu01    :======wawawa
    ======stu02    :======hahaha
          :1
          :0
    

    実は上記のコードにはいくつかの小さな問題があります.あるいは考えが足りないところです.オブジェクトをレプリケーションして初期化(構築)すると、プロファイルエラーが発生します.
    エラーの報告と重大度コード説明項目ファイル行エラーC 4996‘strcpy’:This function or variable may be unsafe.Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. Test f:\cworkspace\test\test\main.c 30用VSコンパイルコードは上記のような問題に遭遇し、vsはstrcpyを廃棄する準備ができており、セキュリティが低いため、マイクロソフトはstrcpyを提供しています.sに代わってstrcpyを使い続けたい場合はmainの前に
    #pragma warning(disable:4996)