バックグラウンド:
最近の初学期は C++ のコース設計を行い、テーマは [成績入力システム] (QT マルチウィンドウ インターフェイスを使用) でした。
生徒情報は複数のウィンドウで共有する必要があるため、複数のクラス間で同じデータを共有する機能を充実させる必要があります。
方法:
次のコードを直接使用するだけです。
ヘッダー ファイル datashare.h:
#ifndef DATASHARE_H
#define DATASHARE_H
#include "grade.h" // 需要共享的数据(在这里是“Grade”类的一个对象)的头文件定义
class DataShare {
protected: // 禁止类外访问,但允许子类访问
DataShare(); // 构造函数,初始化要共享的数据
Grade& grade = sharedData(); // 定义要共享数据的引用(可被修改)
private: // 禁止类外和子类访问
static Grade& sharedData(); // 返回要共享数据的引用(可被修改)
};
#endif // DATASHARE_H
実装ファイル datashare.cpp:
#include "datashare.h"
DataShare::DataShare() { // 初始化要共享的数据,这部分因人而异
this->sharedData() = Grade(); // 一定要赋值给 “this->sharedData()”
this->sharedData().loadJsonFile(":/grade.json");
}
Grade& DataShare::sharedData() { // 返回要共享数据的引用(可被修改)
static Grade dataShare; // 这里是真正要共享的数据本体
return dataShare;
}
例証します:
① 上記のコードでは、datashare は共有する必要があるデータです (datashare はグレード全体のデータを保存する Grade クラスのインスタンスです)。この部分は共有したいインスタンスに変更する必要があります。または、他の種類のデータでも構いません。
② 共有する必要があるオブジェクト/データはコンストラクターで初期化する必要があります。
③ 共有方法: クラス A、B、C 間でデータ グレードを共有する必要がある場合、クラス A、B、C で同時に DataShare クラスを継承するだけで、クラス A、B、C で DataShare クラスのグレード メンバーを (自分のメンバーと同じように) 直接使用できます。
例:
これで、グレード全体のデータ (グレード オブジェクトに保存され、グレード オブジェクトは DataShare クラスに保存されます) を共有する必要があるウィンドウが 4 つになり、次のように DataShare クラスから継承するだけで済みます。
class AddWindow : public QWidget, protected DataShare
class MainWindow : public QMainWindow, protected DataShare
class ManageWindow : public QWidget, protected DataShare
class StatWindow : public QWidget, protected DataShare
このうち、「, protected DataShare」は新たに追加されたコードです。
原理:
もちろん、クラス内で静的メンバーを定義するとデータ共有を実現できますが、C++ の静的メンバーはクラスの外部に割り当てる必要があり、すべてのクラスにはクラス名を介して直接アクセスできます (プライベート メンバーとして使用することはできません。クラスのメンバーのカプセル化保護が破られるため、「DataShare::grade」のような方法でアクセスする必要がありますが、これは非常に洗練されていません)。考えた結果、非常に賢い方法を見つけました (コードを参照)。
実際のデータは、 DataShare クラスのsharedData メンバー関数の静的変数static Grade dataShareに格納されます。そうすることで、静的メンバーをクラス外で初期化する必要があるという欠点が回避されます。
DataShare::DataShare()コンストラクターが実行されると、次のステートメントが実行されます: this->sharedData() = Grade(); 新しく作成されたGradeオブジェクトは、 sharedData関数に割り当てられます(何ですか? 関数も割り当てることができます?)。代入できる理由は、sharedData が戻り値が参照となる関数として定義されているためです。このように、this->sharedData() = Grade() は、割り当てられているsharedData関数の静的変数dataShareと同等になります。共有されることが期待されるデータはGradeであるため、sharedData はプライベート関数として定義され、サブクラスがアクセスできないようにします。
Grade& Grade =sharedData(); を見てみましょう。 Grade は、データのカプセル化を保証し、サブクラスによって継承できる、保護された型のメンバー変数として定義されます。実際に使用する場合は、 Gradeに直接代入するか、 Gradeを呼び出すことができます。理由: Gradeメンバー変数は、sharedData静的関数の戻り値への参照であり、 sharedData の戻り値は、 sharedData関数の静的変数dataShareへの参照です。このように、gradeメンバ変数に直接アクセスすると、それは直接クラスの静的関数内の静的変数への参照とみなされ、関数の静的変数が静的記憶領域に格納されていることは誰もが知っています。また、関数は静的関数であり、変数は静的変数であるため、実際のデータはプログラム全体にのみ保存され、コピーは 1 つだけ保存されます。この方法では、 DataShareから継承したクラスの数に関係なく、クラスは 1 つのグレード(データ) のみを共有し、保護されたメンバーGrade& Grade =sharedData()が継承されるため、独自のクラスでグレードメンバー変数を直接使用できます。この方法により、異なるクラス間での正確なデータ共有が実現できる。
ここまでで、C++ で複数のクラス間でデータ共有を実装する方法に関するこのチュートリアルは終了しました。まだご質問がある場合は、コメント欄または小さなウィンドウにプライベートメッセージを残してください~~