C ++クラスとオブジェクトの学習[パート2:オブジェクトの特性]
コンストラクタとデストラクタ
オブジェクトの初期化とクリーンアップを完了します。
コンパイラはそれを自動的に呼び出すように強制されます。
コンストラクター構文:
クラス名(){}
デストラクタ構文:
〜クラス名(){}
コンストラクターの分類と呼び出し
分類方法:
- パラメータによる分類:パラメータ化された構造とパラメータ化されていない構造
- タイプ別分類:通常構造とコピー構造
3つの呼び出しメソッド:
- ブラケット
- 表示方法
- 暗黙の変換
具体的な手順は次のとおりです。
// arrayone.cpp -- small arrays of integers
#include <iostream>
using namespace std;
//构造函数的分类和调用
class Person
{
public: //一定要写在public权限之下
Person()
{
cout << "无参构造" << endl;
}
Person(int a)
{
age = a;
cout << "有参构造" << endl;
}
Person(const Person &p) //记住这种写法先,完成拷贝一份一样的进行构造
{
cout << "拷贝构造" << endl;
//将传入Person身上的属性,拷贝到当前类上
age = p.age;
}
~Person()
{
cout << "析构" << endl;
}
int age;
};
int main()
{
//括号法
Person p1; //默认构造函数(无参构造)
Person p2(10); //有参构造
Person p3(p2); //拷贝构造
//注意事项:调用默认构造函数时,不要加(),否则就会认为是函数声明
cout << "p2's age = " << p2.age << endl;
cout << "p3's age = " << p3.age << endl;
//显示法
Person p4;
Person p5 = Person(99);
Person p6 = Person(p5);
//单独一个这个,是匿名对象,当前行结束,系统立即回收匿名对象
Person(50);
//注意事项:不要利用拷贝构造,初始化匿名对象,编译器认为是Person(p3) === Person p3;
//隐式法
Person p7 = 10; //相当于Person p7 = person(10);(有参构造)
Person p8 = p7; //拷贝构造
system("pause");
return 0;
}
さまざまな呼び出しメソッドで使用されるさまざまなタイプのコンストラクターを次に示します。
コピーコンストラクターを呼び出すタイミング
使用法:
- すでに構築されたオブジェクトで新しいオブジェクトを初期化します
- 関数パラメーターに値を渡す値を渡す
- ローカルオブジェクトを値で返す
// arrayone.cpp -- small arrays of integers
#include <iostream>
using namespace std;
//构造函数的分类和调用
class Person
{
public:
Person()
{
cout << "Person的默认构造函数调用" << endl;
}
Person(int age)
{
age_ = age;
cout << "Person的有参构造函数调用" << endl;
}
Person(const Person &p)
{
age_ = p.age_;
cout << "Person的拷贝构造函数调用" << endl;
}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
int age_;
};
//使用一个已经构建的对象初始化一个新对象
void test01()
{
Person p1(20);
Person p2(p2);
}
//值传递给函数参数传值
void doit(Person p)
{
}
void test02()
{
Person p;
doit(p);
}
//以值方式返回局部对象
Person donow()
{
Person p1;
return p1;
}
void test03()
{
Person p = donow();
}
int main()
{
//test01();
//test02();
test03();
system("pause");
return 0;
}
さまざまなメソッドでコピーコンストラクターを呼び出す(メソッドを呼び出す)タイミングを示します。
注:コピーコンストラクターの定義方法は、次のように特別です。
Person(const Person &p)
{
age_ = p.age_;
cout << "Person的拷贝构造函数调用" << endl;
}
いわゆるコピー構築は、特にローカルオブジェクトを値で返すために、新しいクラスをコピーすることです。関係するのは、新しいオブジェクトを返すことです。このオブジェクトは、p1のオントロジーではありません。p1のオントロジーになりたい場合、返される必要があるのは参照です。つまり、次のとおりです。
return *this;
また、関数の戻り値の型は参照です。つまり、次のようになります。
Person& (const Person &p)
{
age_ = p.age_;
cout << "Person的拷贝构造函数调用" << endl;
}
コンストラクター呼び出しルール
クラスを作成すると、C ++コンパイラは各クラスに少なくとも3つの関数を追加します。
注:パラメーター化されたコンストラクターが作成された場合、デフォルトでは自動的に作成されなくなりますが、コピーの作成は引き続き提供されます。
ここでのコピー構成は、クラスA情報をクラスBにコピーするための代入ステートメントを自動的に追加することとして理解できます。
注:コピーコンストラクターを作成すると、コンパイラーは他の通常のコンストラクターを提供しなくなります。
これらの2つの注意事項は、コンパイラーが提供しない独自のコンストラクター(使用する場合)を作成する必要があることを意味します。
ディープコピーとシャローコピー
浅いコピー:単純な割り当て
深いコピー:
浅いコピーの問題のためにヒープ領域のメモリスペースを再適用する:ヒープ領域のメモリを繰り返し解放する
リストを初期化してプロパティを初期化します
属性の値を初期化するための初期化リストを次に示します。手順は次のとおりです。
// arrayone.cpp -- small arrays of integers
#include <iostream>
using namespace std;
//构造函数的分类和调用
class Person
{
public:
//传统初始化操作
// Person(int a, int b, int c)
// {
// A_ = a;
// B_ = b;
// C_ = c;
// }
//通过初始化列表初始化属性
Person() : A_(10), B_(20), C_(30)//不必注释该行,因为可以利用构造函数重载实现
{
}
//或者
Person(int a, int b, int c) : A_(a), B_(b), C_(c)
{
}
int A_;
int B_;
int C_;
};
void test01()
{
//Person p(10, 20, 30);
// Person p;
Person p(30, 20, 10);
cout << "A_ = " << p.A_ << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
ここでは、3つの初期化方法を紹介します。
その中で、従来の初期化では、パラメーター化されたコンストラクターを使用して、値を渡して初期化します。
さらに、2番目のタイプはリストの初期化ですが、このタイプのリストは繰り返されないため、固定値にのみ初期化できます。
3番目のタイプの初期化は、基本的に最初のタイプのアップグレードと変換です。これは、記述を簡素化し、一目でわかりやすく、非常に便利です。
ここでは、関数のオーバーロードが使用されています。この例では、2つのコンストラクターが予約されており、呼び出し時に関数のオーバーロードをトリガーして、適切なコンストラクターを選択できます。
(作者はそれが間違いだと思い、最後のコンストラクターをコメントアウトしようとしましたが、操作が正しいことがわかりました。その後、Baiduは関数のオーバーロードがあることを発見し、それを尊重しなければなりませんでした!)
クラスメンバーとしてのクラスオブジェクト
クラスを定義するときに、他のクラスをクラスメンバーとして定義できます。この関数は次のコードで示され、初期化リストが追加されます。
// arrayone.cpp -- small arrays of integers
#include <iostream>
using namespace std;
#include <string>
//类对象作为类成员
class Phone
{
public:
Phone(string PName) : PName_(PName)
{
//PName_ = PName;
cout << "Phone构造函数" << endl;
}
string PName_;
};
class Person
{
public:
//相当于: Phone phone_ = PName;
Person(string name, string PName) : name_(name), phone_(PName)
{
cout << "Person构造函数" << endl;
}
string name_;
Phone phone_;
};
//当其他类对象作为本类成员,先构造其他类对象,再构造自身
//析构的顺序正好相反
void test01()
{
Person p("张三", "苹果手机");
cout << p.name_ << "拿着" << p.phone_.PName_ << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
また、この方法を適用すると、他のオブジェクトが最初に作成され、次にそれ自体が作成され、破棄の順序がまったく逆になることに注意してください。
これは、完全なクラスにアセンブルできる既存のパーツとして理解できるため、使用されるクラスオブジェクトが最初に構築されます。
プログラムの結果は次のとおりです。
静的メンバー
静的メンバーは、静的メンバーと呼ばれる、メンバー変数およびメンバー関数の前にキーワードstaticを追加することです。
静的メンバーは次のように分けられます。
- 静的メンバー変数
- すべてのオブジェクトが同じデータを共有します
- コンパイル中にメモリを割り当てます
- クラス内宣言、クラス外初期化
- 静的メンバー関数
- すべてのオブジェクトは同じ機能を共有します
- 静的メンバー関数は静的メンバー変数にのみアクセスできます
私は静的変数についての良い記事を見つけました:
https://blog.csdn.net/ichliebecamb/article/details/85097922?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai 1.比較する