//: C09:VirtualBase.cpp // Shows a shared subobject via a virtual base. #include <iostream> using namespace std; class Top { protected: int x; public: Top(int n) { x = n; } virtual ~Top() {} friend ostream& operator<<(ostream& os, const Top& t) { return os << t.x; } }; class Left : virtual public Top { protected: int y; public: Left(int m, int n) : Top(m) { y = n; } }; class Right : virtual public Top { protected: int z; public: Right(int m, int n) : Top(m) { z = n; } }; class Bottom : public Left, public Right { int w; public: Bottom(int i, int j, int k, int m) : Top(i), Left(0, j), Right(0, k) { w = m; } friend ostream& operator<<(ostream& os, const Bottom& b) { return os << b.x << ',' << b.y << ',' << b.z << ',' << b.w; } }; int main() { Bottom b(1, 2, 3, 4); cout << sizeof b << endl; cout << b << endl; cout << static_cast<void*>(&b) << endl; Top* p = static_cast<Top*>(&b); cout << *p << endl; cout << static_cast<void*>(p) << endl; cout << dynamic_cast<void*>(p) << endl; } ///:~
Listado 8.12. C09/VirtualBase.cpp
36 1,2,3,4 1245032 1 1245060 1245032
//: C09:VirtualBase2.cpp // How NOT to implement operator<<. #include <iostream> using namespace std; class Top { int x; public: Top(int n) { x = n; } virtual ~Top() {} friend ostream& operator<<(ostream& os, const Top& t) { return os << t.x; } }; class Left : virtual public Top { int y; public: Left(int m, int n) : Top(m) { y = n; } friend ostream& operator<<(ostream& os, const Left& l) { return os << static_cast<const Top&>(l) << ',' << l.y; } }; class Right : virtual public Top { int z; public: Right(int m, int n) : Top(m) { z = n; } friend ostream& operator<<(ostream& os, const Right& r) { return os << static_cast<const Top&>(r) << ',' << r.z; } }; class Bottom : public Left, public Right { int w; public: Bottom(int i, int j, int k, int m) : Top(i), Left(0, j), Right(0, k) { w = m; } friend ostream& operator<<(ostream& os, const Bottom& b){ return os << static_cast<const Left&>(b) << ',' << static_cast<const Right&>(b) << ',' << b.w; } }; int main() { Bottom b(1, 2, 3, 4); cout << b << endl; // 1,2,1,3,4 } ///:~
Listado 8.13. C09/VirtualBase2.cpp
//: C09:VirtualBase3.cpp // A correct stream inserter. #include <iostream> using namespace std; class Top { int x; public: Top(int n) { x = n; } virtual ~Top() {} friend ostream& operator<<(ostream& os, const Top& t) { return os << t.x; } }; class Left : virtual public Top { int y; protected: void specialPrint(ostream& os) const { // Only print Left's part os << ','<< y; } public: Left(int m, int n) : Top(m) { y = n; } friend ostream& operator<<(ostream& os, const Left& l) { return os << static_cast<const Top&>(l) << ',' << l.y; } }; class Right : virtual public Top { int z; protected: void specialPrint(ostream& os) const { // Only print Right's part os << ','<< z; } public: Right(int m, int n) : Top(m) { z = n; } friend ostream& operator<<(ostream& os, const Right& r) { return os << static_cast<const Top&>(r) << ',' << r.z; } }; class Bottom : public Left, public Right { int w; public: Bottom(int i, int j, int k, int m) : Top(i), Left(0, j), Right(0, k) { w = m; } friend ostream& operator<<(ostream& os, const Bottom& b){ os << static_cast<const Top&>(b); b.Left::specialPrint(os); b.Right::specialPrint(os); return os << ',' << b.w; } }; int main() { Bottom b(1, 2, 3, 4); cout << b << endl; // 1,2,3,4 } ///:~
Listado 8.14. C09/VirtualBase3.cpp
//: C09:VirtInit.cpp // Illustrates initialization order with virtual bases. #include <iostream> #include <string> using namespace std; class M { public: M(const string& s) { cout << "M " << s << endl; } }; class A { M m; public: A(const string& s) : m("in A") { cout << "A " << s << endl; } virtual ~A() {} }; class B { M m; public: B(const string& s) : m("in B") { cout << "B " << s << endl; } virtual ~B() {} }; class C { M m; public: C(const string& s) : m("in C") { cout << "C " << s << endl; } virtual ~C() {} }; class D { M m; public: D(const string& s) : m("in D") { cout << "D " << s << endl; } virtual ~D() {} }; class E : public A, virtual public B, virtual public C { M m; public: E(const string& s) : A("from E"), B("from E"), C("from E"), m("in E") { cout << "E " << s << endl; } }; class F : virtual public B, virtual public C, public D { M m; public: F(const string& s) : B("from F"), C("from F"), D("from F"), m("in F") { cout << "F " << s << endl; } }; class G : public E, public F { M m; public: G(const string& s) : B("from G"), C("from G"), E("from G"), F("from G"), m("in G") { cout << "G " << s << endl; } }; int main() { G g("from main"); } ///:~
Listado 8.15. C09/VirtInit.cpp
M in B B from G M in C C from G M in A A from E M in E E from G M in D D from F M in F F from G M in G G from main