この一連のC++ 関連記事は、あくまで著者の学習メモであり、私自身の理解に基づいて学習を記録していきます。C++ 学習シリーズは、基礎、STL、および高度なデータ構造とアルゴリズムの3 つの段階に分かれており、関連する主な内容は次のとおりです。
- 基本:クラスとオブジェクト(C++ の 3 つの主要な機能など)。
- STL : C++ が提供する STL 関連ライブラリの使用方法を学びます。
- 高次データ構造とアルゴリズム:独自の STL ライブラリを手動で実装し、 B ツリー、B+ ツリー、赤黒ツリーなどの高次データ構造を設計および実装します。
学習セット:
この号の内容: [C++ 基礎: 22]: クラスの const メンバー変数/属性と const メンバー関数/メソッド、およびクラス内の const に関連する一般的な問題!
内容:
1. const メンバー関数の基本的な理解
2. コード例で議論すべき質問: クラスの const オブジェクト
- - 2.1 直接的な式の分析
- - 2.2 コード分析との組み合わせ
3. const メンバー関数の書き方!
- - 3.1 基本的な書き方の枠組み
- - 3.2 エラーコード例の修正とテスト結果
4. クラスの const に関するよくある問題!
5. おすすめ関連記事
[ C++学習集リンク]
1. const メンバー関数の基本的な理解
- const で変更された「メンバー関数」を const メンバー関数と呼びます。
- const はクラスのメンバー関数を変更し、実際にはメンバー関数内で暗黙的に this ポインターを変更します。これは、クラスのメンバーがメンバー関数内で変更できないことを示します。(理解方法については、2つ目の分析ポイントと3つ目のポイントの実際の使用方法を参照してください)
注: これには、前のコンテンツで説明したクラスの *この問題が含まれます:クリックすると、関連する記事に直接移動します
2. 問題を議論するためのコード例!
コードを読むときは、const で変更されたメンバー関数の意味を思い出してください。メンバー関数の暗黙的な this ポインターの実際の変更は、メンバー関数内でクラスのメンバーを変更できないことを示します。
質問: 次のコードは正常に実行できますか? [分析と議論、コードの後のテキスト内容を見てください]
#include<iostream>
using std::cout;
using std::endl;
class Date {
public:
Date(int year = 2000, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
// 此前学习的基本示例化方式
Date d1(2023, 5, 23);
// 使用 const 修饰实例化对象!
const Date d2(2023, 5, 24);
d1.Print();
d2.Print();
return 0;
}
操作結果:
2.1 直接的な発現解析
画像からわかるように、プログラムはエラーを報告します。上記のコードでは、インスタンス化の例で const 変更が使用されています。前回のクラスの紹介で述べたことを思い出してください。クラスは、「*this ポインター」を通じてさまざまなインスタンス オブジェクトの識別を実現します。先ほど説明した「*this ポインター」は、クラス内のメンバー関数の最初の (隠し) パラメーターです。その形式は次のとおりです: typename* const this !
/* 以构造函数为例 */ void Date( Date* const this, int year, int month, int day){]
明らかに、エラー レポートから、使用している d2 オブジェクトが実際には const 変更されていることがわかります。言い換えれば、 d2 を識別する「*this ポインター」も const で変更する必要があります。しかし、以前の"*this pointer"の紹介を振り返ると、この非表示のデフォルト パラメータの送受信を表示できないと述べました。では、この問題をどうやって解決すればよいでしょうか?
解決策: 前回の紹介によると、const メンバー関数の役割は何ですか?
2.2 コード分析との組み合わせ
まず、インスタンス化された 2 つのオブジェクトに注目してください。(文字通りの違いは、const 変更があるかどうかです。)
// 使用 引用与指针的权限思路理解 Date d1(2023, 5, 23); // 可读可写 const Date d2(2023, 5, 24); // 只可读
Print() 関数に注意してください。パラメータのタイプに注意してください。!!
// 函数字面声明的原型如下: void Print() {} // 实际中编译器会翻译作: void Print(Date* const this){} /* 简而言之,就是隐藏了 this 指针! 且 this 指针是被 const 修饰(注意 const 在 * 之后的意义!!!)! */
インスタンス化された 2 つのオブジェクト自体を振り返ってみます。
// 字面形式 Date d1(2023, 5, 23); const Date d2(2023, 5, 24); // 编译器翻译的形式: Date d1(&d1, 2023, 5, 23); const Date d2(&d2, 2023, 5, 24); /* 注意: &d1、&d2 是什么类型? */
次のステートメントを実行して結果を取得します。
/* 执行以下语句: */ cout << typeid(&d1).name() << endl; cout << typeid(&d2).name() << endl; /* 结果: */ class Date * class Date const *
上記の結果と関数のパラメーターの型を組み合わせると、問題がわかります。
/* &d1:Date * &d2:Date const * 函数参数:Date * 【 const 只是修饰指针的! 】 从权限角度看来,函数接收的是可读可写参数,传递过来的是只读!在函数内使用时就是权限放大(不可行!只能平行或缩小!) 由此:得出问题的关键就是在于参数问题! 由此前知识点可知:类的默认隐含参数是不可以显示接收及传递的!那该如何使 Date * => Date const * 解决方案:const 成员函数【 const 修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。 】 */
3. constメンバー関数の書き方!
3.1 基本的な執筆フレームワーク
基本的な書き方は以下の通りです。
type function_name() const /* 注意 const 的位置及作用 */
{
}
3.2 エラーコード例を変更して結果をテストする
Print() 関数を変更してください。
void Print() const /* 注意此处修改! */
{
cout << _year << "-" << _month << "-" << _day << endl;
}
4. クラス内の const に関連する一般的な問題!
- const オブジェクトは非 const メンバー関数を呼び出すことができますか?
- 非 const オブジェクトは const メンバー関数を呼び出すことができますか?
- const メンバー関数は他の非 const メンバー関数を呼び出すことができますか?
- 他の const メンバー関数を非 const メンバー関数内で呼び出すことはできますか?
- 同じ名前の関数は、const の変更の有無にかかわらずオーバーロードを構成しますか?
ヒント:真実をテストするための唯一の基準は実践です。