Bruce Eckel's Thinking in C++, 2nd Ed | Contents | Prev | Next |
//: C22:Mithis.cpp // MI and the "this" pointer #include <fstream> using namespace std; ofstream out("mithis.out"); class Base1 { char c[0x10]; public: void printthis1() { out << "Base1 this = " << this << endl; } }; class Base2 { char c[0x10]; public: void printthis2() { out << "Base2 this = " << this << endl; } }; class Member1 { char c[0x10]; public: void printthism1() { out << "Member1 this = " << this << endl; } }; class Member2 { char c[0x10]; public: void printthism2() { out << "Member2 this = " << this << endl; } }; class MI : public Base1, public Base2 { Member1 m1; Member2 m2; public: void printthis() { out << "MI this = " << this << endl; printthis1(); printthis2(); m1.printthism1(); m2.printthism2(); } }; int main() { MI mi; out << "sizeof(mi) = " << hex << sizeof(mi) << " hex" << endl; mi.printthis(); // A second demonstration: Base1* b1 = &mi; // Upcast Base2* b2 = &mi; // Upcast out << "Base 1 pointer = " << b1 << endl; out << "Base 2 pointer = " << b2 << endl; } ///:~
sizeof(mi) = 40 hex mi this = 0x223e Base1 this = 0x223e Base2 this = 0x224e Member1 this = 0x225e Member2 this = 0x226e Base 1 pointer = 0x223e Base 2 pointer = 0x224e
//: C22:Persist1.cpp // Simple persistence with MI #include <iostream> #include <fstream> #include "../require.h" using namespace std; class Persistent { int objSize; // Size of stored object public: Persistent(int sz) : objSize(sz) {} void write(ostream& out) const { out.write((char*)this, objSize); } void read(istream& in) { in.read((char*)this, objSize); } }; class Data { float f[3]; public: Data(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) { f[0] = f0; f[1] = f1; f[2] = f2; } void print(const char* msg = "") const { if(*msg) cout << msg << " "; for(int i = 0; i < 3; i++) cout << "f[" << i << "] = " << f[i] << endl; } }; class WData1 : public Persistent, public Data { public: WData1(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) : Data(f0, f1, f2), Persistent(sizeof(WData1)) {} }; class WData2 : public Data, public Persistent { public: WData2(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) : Data(f0, f1, f2), Persistent(sizeof(WData2)) {} }; int main() { { ofstream f1("f1.dat"), f2("f2.dat"); assure(f1, "f1.dat"); assure(f2, "f2.dat"); WData1 d1(1.1, 2.2, 3.3); WData2 d2(4.4, 5.5, 6.6); d1.print("d1 before storage"); d2.print("d2 before storage"); d1.write(f1); d2.write(f2); } // Closes files ifstream f1("f1.dat"), f2("f2.dat"); assure(f1, "f1.dat"); assure(f2, "f2.dat"); WData1 d1; WData2 d2; d1.read(f1); d2.read(f2); d1.print("d1 after storage"); d2.print("d2 after storage"); } ///:~
//: C22:Persist2.cpp // Improved MI persistence #include <iostream> #include <fstream> #include <cstring> #include "../require.h" using namespace std; class Persistent { public: virtual void write(ostream& out) const = 0; virtual void read(istream& in) = 0; virtual ~Persistent() {} }; class Data { protected: float f[3]; public: Data(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) { f[0] = f0; f[1] = f1; f[2] = f2; } void print(const char* msg = "") const { if(*msg) cout << msg << endl; for(int i = 0; i < 3; i++) cout << "f[" << i << "] = " << f[i] << endl; } }; class WData1 : public Persistent, public Data { public: WData1(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) : Data(f0, f1, f2) {} void write(ostream& out) const { out << f[0] << " " << f[1] << " " << f[2] << " "; } void read(istream& in) { in >> f[0] >> f[1] >> f[2]; } }; class WData2 : public Data, public Persistent { public: WData2(float f0 = 0.0, float f1 = 0.0, float f2 = 0.0) : Data(f0, f1, f2) {} void write(ostream& out) const { out << f[0] << " " << f[1] << " " << f[2] << " "; } void read(istream& in) { in >> f[0] >> f[1] >> f[2]; } }; class Conglomerate : public Data, public Persistent { char* name; // Contains a pointer WData1 d1; WData2 d2; public: Conglomerate(const char* nm = "", float f0 = 0.0, float f1 = 0.0, float f2 = 0.0, float f3 = 0.0, float f4 = 0.0, float f5 = 0.0, float f6 = 0.0, float f7 = 0.0, float f8= 0.0) : Data(f0, f1, f2), d1(f3, f4, f5), d2(f6, f7, f8) { name = new char[strlen(nm) + 1]; strcpy(name, nm); } void write(ostream& out) const { int i = strlen(name) + 1; out << i << " "; // Store size of string out << name << endl; d1.write(out); d2.write(out); out << f[0] << " " << f[1] << " " << f[2]; } // Must read in same order as write: void read(istream& in) { delete []name; // Remove old storage int i; in >> i >> ws; // Get int, strip whitespace name = new char[i]; in.getline(name, i); d1.read(in); d2.read(in); in >> f[0] >> f[1] >> f[2]; } void print() const { Data::print(name); d1.print(); d2.print(); } }; int main() { { ofstream data("data.dat"); assure(data, "data.dat"); Conglomerate C("This is Conglomerate C", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9); cout << "C before storage" << endl; C.print(); C.write(data); } // Closes file ifstream data("data.dat"); assure(data, "data.dat"); Conglomerate C; C.read(data); cout << "after storage: " << endl; C.print(); } ///:~