オブジェクトの初期化とクリーンアップ
コンストラクターとデストラクター
オブジェクトの初期化とクリーンアップも 2 つの非常に重要なセキュリティ問題です。
オブジェクトまたは変数は初期化されておらず、その使用の結果は不明です。同様に、オブジェクトまたは変数は使用
後に時間内にクリーンアップされず、これによっても問題が発生します。特定のセキュリティ上の問題を引き起こす可能性があります。
C++ はコンストラクターとデストラクターを使用して上記の問題を解決し、これら 2 つの関数はコンパイラーによって自動的に呼び出され、オブジェクトの初期化とクリーンアップを完了します。
オブジェクトの初期化とクリーンアップはコンパイラによって強制されるものであるため、構築と破棄を提供しない場合、コンパイラはコンパイラによって提供されるコンストラクタとデストラクタを提供しますが、それらはすべて空の実装です。
1. コンストラクター: 主な機能は、オブジェクトの作成時にオブジェクトのメンバー プロパティに値を代入することであり、コンストラクターは手動で呼び出すことなく、コンパイラーによって自動的に呼び出されます。
2. デストラクター: 主な機能は、オブジェクトが破棄される前にシステムが自動的に呼び出して、クリーニング作業を実行することです。
コンストラクターの構文: クラス名 () {}
1. コンストラクター。戻り値も void もありません
。 2. 関数名はクラス名と同じです。
3. コンストラクターにはパラメーターを含めることができるため、オーバーロードが発生する可能性があります
。 4. オブジェクトを呼び出すときに、プログラムは自動的にコンストラクターを呼び出します。必要はありません。手動で呼び出すと、一度だけ呼び出されます
コンストラクター構文: ~class name(){}
1. デストラクター、戻り値なし、void なし
2. 関数名はクラス名と同じで、名前の前に記号が追加されます~
3. デストラクターはパラメーターを持つことができないため、オーバーロードは発生しません
4. プログラムはオブジェクトの destroy は、破棄前に自動的に呼び出されます。手動で呼び出す必要はなく、一度だけ呼び出されます。
人.h
#pragma once
#include<iostream>
using namespace std;
class Person
{
public:
// 1、构造函数,没有返回值也不写void
// 2、函数名称与类名相同
// 3、构造函数可以有参数,因此可以发生重载
// 4、程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次
Person();
// 1、析构函数,没有返回值也不写void
// 2、函数名称与类名相同,在名称前加上符号~
// 3、析构函数不可以有参数,因此不可以发生重载
// 4、程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次
~Person();
int m_num=0;
void setnum(int num);
};
main.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "person.h"
void test01()
{
Person p1;//在栈上的数据,test01执行完毕后,释放这个对象
p1.setnum(1);
}
int main()
{
Person p2;
p2.setnum(2);
test01();
system("pause");
return 0;
}
person.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "person.h"
Person::Person()
{
cout << "Person构造函数的调用" << m_num << endl;
}
Person::~Person()
{
cout << "Person析构函数的调用" << m_num << endl;
}
void Person::setnum(int num)
{
m_num = num;
}
コンストラクターの分類と呼び出し
2 つの分類方法:
パラメータ別: パラメータありの構築とパラメータなしの構築
、タイプ別: 通常の構築とコピー構築、
3 つの呼び出し方法:
ブラケットメソッド、
明示的メソッド、
暗黙的変換メソッド
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Person的无参数构造函数调用" << endl;//无参构造函数(默认构造函数)
}
Person(int a)
{
age = a;
cout << "Person的带参数构造函数调用" << endl;//有参构造函数
}
//拷贝构造函数
Person(const Person &p)
{
age = p.age;
age = p.age;
cout << "Person的拷贝数构造函数调用" << endl;
}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
int age;
};
void test01()
{
//1、括号法
//Person p1;//默认构造函数调用
//Person p2(10);//有参构造函数
//Person p3(p2);
//注意事项
//调用默认构造函数时,不要加()
//因为编译器会认为是一个函数的声明,不会认为在创建对象
//cout << "p2的年龄为:" << p2.age << endl;
//cout << "p3的年龄为:" << p3.age << endl;
//2、显示法
//Person p1;//默认构造函数调用
//Person p2 = Person(10);//有参构造函数
//Person p3 = Person(p2);//拷贝构造函数
//注意事项
//不要利用拷贝构造函数,初始化匿名对象
//Person(10);//匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
//3、隐式转换法
Person p4 = 10;//相当于写了 Person p4 = Person(10);//有参构造函数
Person p5 = p4;
}
int main()
{
test01();
return 0;
}
コピー コンストラクターを呼び出すタイミング
C++ では、通常、コピー コンストラクターが呼び出される状況が 3 つあります
。 1. すでに作成されたオブジェクトを使用して新しいオブジェクトを初期化する
2. 値を値で関数に渡す
3. ローカル オブジェクトを値で返す
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Person的无参数构造函数调用" << endl;//无参构造函数(默认构造函数)
}
Person(int age)
{
m_Age = age;
cout << "Person的带参数构造函数调用" << endl;//有参构造函数
}
//拷贝构造函数
Person(const Person &p)
{
m_Age = p.m_Age;
cout << "Person的拷贝数构造函数调用" << endl;
}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
int m_Age;
};
//1、使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(20);
Person p2(p1);
}
//2、值传递的方式给函数传值
void doWork(Person p)
{
}
void test02()
{
Person p;
doWork(p);
}
//3、以值方式返回局部对象
Person doWork2()
{
Person p1;
return p1;
}
void test03()
{
Person p = doWork2();
}
int main()
{
//test01();
//test02();
test03();
system("pause");
return 0;
}
自分で探検してみましょう: ☆
1. クラスにコンストラクターがある場合、コンパイラーはデフォルトのコンストラクターを追加しません。
2. クラスのプログラマーがコピー コンストラクターを作成するときに、コピー関数がコピーする必要がある別のクラスにすべてのメンバー変数を割り当てていない場合、呼び出し値が渡されるときに、これらの定数の値はコピーされません。
コンストラクター呼び出しルール
デフォルトでは、C++ コンパイラーは少なくとも 3 つの関数をクラスに追加します。
1. デフォルトのコンストラクター (パラメーターなし、関数本体は空)
2. デフォルトのデストラクター (パラメーターなし、関数本体は空)
3. 値をコピーするためのデフォルトのコピー コンストラクター属性の
コンストラクターの呼び出し規則は次のとおりです:
1. ユーザーがパラメーターを使用してコンストラクターを定義した場合、C++ はデフォルトの引数なしの構造を提供しなくなりましたが、デフォルトのコピー構造を提供します 2. ユーザーがコピー コンストラクターを定義した場合、C
++他のコンストラクターは提供しません
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Person的无参数构造函数调用" << endl;//无参构造函数(默认构造函数)
}
Person(int age)
{
m_Age = age;
cout << "Person的带参数构造函数调用" << endl;//有参构造函数
}
//Person(const Person &p)//*(Person* const p)
//{
// m_Age = p.m_Age;
// cout << "Person的拷贝数构造函数调用" << endl;//拷贝构造函数
//}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
int m_Age;
};
void test01()
{
Person p;
p.m_Age = 18;
Person p2(p);
cout << "p2的年龄为:" << p2.m_Age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
#include<iostream>
using namespace std;
class Person
{
public:
//Person()
//{
// cout << "Person的无参数构造函数调用" << endl;//无参构造函数(默认构造函数)
//}
Person(int age)
{
m_Age = age;
cout << "Person的带参数构造函数调用" << endl;//有参构造函数
}
//Person(const Person &p)//*(Person* const p)
//{
// m_Age = p.m_Age;
// cout << "Person的拷贝数构造函数调用" << endl;//拷贝构造函数
//}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
int m_Age;
};
//void test01()
//{
// Person p;//报错
// p.m_Age = 18;
// Person p2(p);
// cout << "p2的年龄为:" << p2.m_Age << endl;
//}
void test02()
{
Person p(28);
Person p2(p);
cout << "p2的年龄为:" << p2.m_Age << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}