私が直面している問題は、カプセル化と最適なメモリ使用をどのように組み合わせるかです。
私のコードをお見せすることはできないので、広範な (願わくば) 例で説明します。
男性のデータベースが必要だとしましょう。私たちが知りたいのは、それらの人々について 2 つのことだけです。
- 男性の年齢 (誕生からの時間)。
- 彼が住んでいる町の名前。
このデータを管理する便利で自然な方法は、人間に対応するオブジェクトを作成し、それらを配列に格納することです。
class OMan1 {
public:
OMan( const int &age, const astring &t ): fAge(age), fTown(t) {}
const int& age() const: { return fAge; }
const astring& Town() const: { return fTown; }
astring FullId() const: { return fTown+fAge; }
private:
int fAge;
astring fTown;
}
OMan mans[N];
ここで、OMan は自己完結型のオブジェクトであり、すべてが適切に満たされます。
町の名前を何千回も複製し、このようにメモリと実行時間を浪費するという事実を除いて.
私たちができる改善は、町の名前と各 OMan ストアの独立した配列を、町の年齢と町の配列へのポインタのみにすることです。
class OMan2 {
// same functionality as for OMan1
int fAge;
int fTownId;
astring* fTowns;
}
オブジェクトはまだ自己完結型であり、sizeof(int) + sizeof(void*) は sizeof(astring) よりもはるかに小さく、多くの勝利を収めています。それでも sizeof(fAge) よりも 2 ~ 3 倍多く、fTowns を何十億回も繰り返します。
メモリの最適化は私にとって非常に重要です。したがって、fAge と fTownId のみを保持し、Town() や FullId() などの機能を OMan クラスから OManDataBase クラスに移動します。
class OMan3 {
public:
OMan( const int &age, const int &tid ): fAge(age), fTownId(tid) {}
const int& age() const: { return fAge; }
const int& TownId() const: { return fId; }
// const astring& Town() const: { return fTown; }
// astring FullId() const: { return fTown+fAge; }
private:
int fAge;
int fTownId;
}
class OManDataBase {
// constructor, destructor
const int& age( const int& i) const: { return fMans[i].TownId()]; }
const astring& Town( const int& i) const: { return fTown[fMans[i].TownId()]; }
const astring& FullId( const int& i) const: { return Town(i)+age(i); }
private:
vector<OMan3> fMans;
vector<astring> fTowns;
}
また、OMan3 は現在、自己完結型のオブジェクトではありません。たとえば、それがフルネームであることを知りません。つまり、1 人でデータ処理を行う必要がある場合は、OManDataBase インスタンス全体を使用する必要があります。
OBillType47 NewBillType47( const OManDataBase &db, int i ) { ... }
それ以外の
OBillType47 NewBillType47( const OMan &m ) { ... }
ここではカプセル化が破られており、コードの可読性が明らかに低下しています。(Type47 は、Oman-S で動作する多くの関数を持つことができ、それらすべてを OManDataBase クラスに含めることはできないことを強調するために付けました)。
オブジェクトを可能な限り自己完結型に保ちながら、データ複製の問題を解決する他の方法(-s)があるのだろうか?