C++におけるコンストラクション関数のまとめ

7677 ワード

classのコンストラクション関数1、オブジェクトの作成時に自動的に呼び出される関数は、オブジェクトのライフサイクル全体で必ず1回呼び出され、1回しか呼び出されません.2、コンストラクション関数では、メンバー変数の初期化、リソースの割り当て、オブジェクトの初期状態の設定を担当します.3、コンストラクション関数には複数のバージョンがあり、これらの異なるバージョン間でリロードが構築され、オブジェクトの作成方法が異なり、与えられたパラメータが異なると対応するコンストラクション関数が呼び出され、呼び出されたコンストラクション関数が存在しない場合、コンパイルエラーが発生する可能性があります.//無パラメトリック構造Student stu<=>Student*stup=new Student;Student stu(パラメータリスト)<=>Student*stup=new Student(パラメータリスト);4、クラスにコンストラクション関数が定義されていない場合、コンパイラは自動的に無パラメトリック構造を生成します.他のバージョンのコンストラクション関数を定義すると、非パラメトリックコンストラクションは生成されません.したがって、非パラメトリック作成オブジェクトのエラーを防止するために、コンストラクション関数を定義する際には、少なくとも2つを実装する必要があります.5、無パラメトリック構造は必ずしも無パラメトリックではなく、C++の関数にはデフォルトパラメータがあり、有パラメトリック構造がすべてデフォルトパラメータを設定している場合、無パラメトリック構造と衝突し、2つは1つしか存在しない.6、いわゆる「コンパイラ生成の○○関数」「コンパイラ生成の○○関数」は、本当の意味での関数ではなく、コンパイルは命令の生成者として、いくつかの関数機能を持つ命令、すなわち、高度な言語を生成しなければならない主義的な関数を生成しなければならない.7、無パラメトリック構造a、Student stu<=>Student*stup=new Studentをいつ呼び出すか.b、オブジェクト配列を作成し、各オブジェクトが無パラメトリック構造を呼び出す.c.クラスAのメンバーがクラスBである場合、クラスAのコンストラクタを実行する前にクラスBの無パラメトリック構造が自動的に呼び出される.d、クラスAでクラスBのパラメトリッククラスA(パラメータリスト):メンバークラスB(パラメータリスト){...}8、タイプ変換コンストラクタは1つのデータでオブジェクトを初期化し、デフォルトではコンストラクタが自動的に呼び出され、タイプ変換の効果を達成します.この方法は使いやすいが、コードチェックをより厳格にするにはexplicitキーワードを使用して暗黙的な変換を禁止する方法でコンストラクション関数を呼び出すことができるエラーも含まれている.9、自動タイプ変換コンストラクタ(デフォルト)を実装することもできます.
次に例を示します.
Dateクラスを定義します:year,month,day,クラスに1、年月日が有効かどうか、boolタイプ2、閏年かどうか、boolタイプ3、nextday()を返し、次の日の日付4を返し、nextday(int n)を書いてn表の後の日付を表します.
#include 
#include

#include
using namespace std;
class MyDate
{
public:
	MyDate(int y, int m, int d);
//	MyDate ();
	void input();
	void judge(int x);//  
	void output(int x);
//	int get_year();
//	int get_month();
//	int get_day();
private:
	void check();
	int year;
	int month;
	int day;
	int a;
	int sum;
};
void MyDate::input ()
{
	cout << "         
"; cout << "
"; cin >> year ; cout << "
"; cin >> month;//year XXX; cout << "
"; cin >> day; check(); } void MyDate::judge(int x) { int i = month -1; if(year%4 ==0&&year%100!=0)// 366 { int mon[12] = {30,29,31,30,31,30,31,31,30,31,30,31};// sum = mon[i] - day; if(sum12) { month=month-12; year++; } } else { a=0; day = day + x; } if(a) { day = sum - x; } } else// 365 { int mon[12] = {30,28,31,30,31,30,31,31,30,31,30,31}; sum = mon[i] - day; if(sum12) {month=month-12; year++;} } else { a=0; day= day+ x;} if(a) { day = sum- x; } } } /* int MyDate::get_year() { return year; } int MyDate::get_month() { return month; } int MyDate::get_day() { return day; } */ void MyDate::check() { if(month < 0 || month > 12) { cout << " error.
"; exit(1); } else { if(month==4 ||month==6 ||month==9 ||month==11) { if(day <0 || day>30 ) { cout << " error.
"; exit(1); } } if(month==2 && day>29) { cout << " error.
"; exit(1); } if(month==3 ||month==5 ||month==7 || month==8 ||month==10||month==12) { if(day>31 ||day<0) { cout << " error.
"; exit(1); } } } } MyDate::MyDate(int y, int m, int d) { year = y; month = m; day = d; } /* MyDate::MyDate() { // ; } */ void MyDate::output (int x) { cout << " " << x << " " << year << " " << month << " " << day<< " "; cout << endl; } int main () { MyDate date(2018,8,7); //date.input(); int X; cout << " .
"; //date.input(); cout << " .
"; cin >> X; date.judge(X); date.output (X); return 0; }

ここのコンストラクション関数は2つあり、それらは重荷を構成しています!2つのより重要な構造関数を引き続き見てみましょう
一、コピー構造関数
1、特殊なコンストラクション関数であり、既存のオブジェクトで同類のコピーオブジェクト、すなわちオブジェクトクローンを構築する.クラス名{クラス名(クラス名&that){クラスメンバーに付与...}}2、コンパイラは、クラスの各メンバーをバイト単位でコピーするコピーコンストラクタコンパイルによって生成されたコピーコンストラクタをデフォルトで生成します.クラスAにクラスBメンバーが存在する場合、クラスAのコピー構造でクラスBのコピー構造が自動的に呼び出されます.3、プログラマは、デフォルトのコピー構造の代わりにコピー構造をカスタマイズすることができます.a、コピー構造は一つしかなく、リロードできない.b、プログラマがカスタマイズしたコピー構造を作成すると、コンパイラは生成されません.c、カスタムコピー構造において、符号化によりメンバーのコピーを実現できる.4、一般的にコンパイラが生成したコピー構造は十分で、簡単に構造をカスタマイズしないでください.
5、どのような場合にコピー構造を呼び出すか:a、オブジェクトとオブジェクトの付与b、オブジェクトと関数でcを参照し、オブジェクトを戻り値とする
もう1つの例を見てみましょう.学生クラスclass Studio{char*name;char sex;short ageが知られています.    };     Student stu1;     Student stu2 = stu1;     stu.name = new char[20]; このような使用中に、セグメントエラー、データ損失、メモリ漏洩が発生することがあります.このような改善方法を説明します.
#include
#include
using namespace std;

class Student
{
	char* name;
	char sex;
	int  age;

public:
	Student(){}
	Student(const char* _name,char _sex,char _age)
	{
		name = new char[strlen(_name)+1];
		strcpy(name,_name);
		sex=_sex;
		age=_age;
	}
	Student(Student& stu)
	{
		//Student newstu=new Student;
		cout<name=new char;
	//("haha",'m',15);
	stu->show();
	//Student* stu2=new Student("hahaaaa",'m',15);
	Student stu1=*stu;
	stu1.show();


}

クラスでは、メンバー変数にポインタ変数がある場合は、newとdeleteを使用してメモリを管理する必要があります.
二、賦値構造関数
付与構造1、付与構造は、あるオブジェクトが別のオブジェクトに付与されたときに呼び出される関数である.        stu2 = stu1;//付与構造
        Student stu2 = stu1;//コピー構造
        void func(Student stu);//コピー構造func(stu 1);
Studio func(void)/コピー構造{return*this;}Studio stu=func()2、付与構造関数のフォーマットvoid operator=(Studio&that){
    }
//他のオブジェクトと対話できるStudent&operator=(Student&that){
    }
3、コンパイラはデフォルトで値付与構造を生成し、その機能はコピー構造の機能と同様に、オブジェクトAをオブジェクトBに完全にコピーする.
4、賦値構造もコピー構造の区別コピー構造:オブジェクトAを使用してオブジェクトBを作成する(呼び出し時にオブジェクトBが生成される).付与構造:オブジェクトAとオブジェクトBが既に構築済みで、このときB=A;オブジェクトに常連メンバーコピー構造がある場合は正常に呼び出されますが、付与構造はできません.5、一般的にデフォルトの割り当て構造は基本的に十分です.メンバーがポインタであり、追加のメモリ領域を指していない限り、コピー構造、割り当て構造をカスタマイズする必要があります.6、カスタム付与構造a、付与構造のフォーマットbを決定し、自己付与int num=1を防止する.            num = num; c、古いリソースdの解放、新しいリソースeの割り当て、新しいコンテンツのコピー
注意**************はコピー構造と似ています.コピー構造:オブジェクトAを使用してオブジェクトBを作成します(呼び出すとオブジェクトBが生成されます).付与構造:オブジェクトAとオブジェクトBが既に構築済みで、このときB=A;これは両者の主な違いである.つまり、異なる文を使用すると、異なるコンストラクション関数が呼び出されます.
次に、付与構造の例を示します.
#include 
#include 

using namespace std;

class Student
{
	char* name;
	char sex;
	mutable short age;
public:
	Student(const char* _name="",char sex='f',short age=1):sex(sex),age(age)
	{
		name = new char[strlen(_name)+1];
		strcpy(name,_name);
	}
	
	Student(const Student& that)
	{
		name = new char[strlen(that.name)+1];
		strcpy(name,that.name);
		sex = that.sex;
		age = that.age;
	}

	void show(void) const
	{
		cout << name << " " << age << endl;
	}

	void show(void)
	{
		cout << name << " " << age << endl;
	}

	void addAge(void) const
	{
		age++;
	}

	void operator = (Student& that)
	{
		if(this == &that) return;
		//      
		delete[] name;
		Student(that);
		/*
		//      
		name = new char[strlen(that.name)+1];
		//      
		strcpy(name,that.name);
		sex = that.sex;
		age = that.age;
		*/
	}

	~Student(void)
	{
		delete[] name;
	}
};

int main()
{
	Student s1("lili",'m',33);
	s1.show();
	Student s2 = s1;
	s2.show();
	s2.addAge();
	s2.show();
	s2 = s1;
	s2.show();
}

要するに、クラスには通常空のコンストラクション関数があります.これにより、オブジェクトの作成時に初期化がなければ、このコンストラクション関数が自動的に呼び出されますが、自分が書いた初期化コンストラクション関数ではデフォルト値を与えることはできません.そうしないと、競合し、再ロードを構成しないことに注意してください.