int main() { Base a(2); a.print(); Sub s; s.print(); return 0; }
int main(int argc, char** argv) { // 6.1 // Private member can NOT be called by subclass Sub object; object.put(100); // error: ‘void Super::put(int)’ is inaccessible within this context object.put(object.get() + 1); cout << object.get() << endl; // 'storage' is not accessible by declare 'private', should be 'protected' object.print(); // error: ‘int Super::storage’ is protected within this context // 'storage' is still not accessible even as 'protected', should be public // cout << object.storage << endl; // 6.2 /* // subclass pointer CAN be converted to superclass pointer implicitly. Pet *a_pet1 = new Cat("Tom"); Pet *a_pet2 = new Dog("Spike"); Pet *a_pet3 = new Bird("Poly"); a_pet1 -> Run(); a_pet2 -> Run(); a_pet3 -> Run(); // is not allowed here! since a_pet1 is superclass pointer // a_pet1 -> MakeSound(); // error: ‘class Pet’ has no member named ‘MakeSound’ // a_pet2 -> MakeSound(); // error: ‘class Pet’ has no member named ‘MakeSound’ // Use static_cast to explicitly convert superclass pointer to subclass pointer static_cast<Cat *>(a_pet1) -> MakeSound(); static_cast<Dog *>(a_pet2) -> MakeSound(); static_cast<Bird *>(a_pet3) -> Laugh(1); cout << static_cast<Cat *>(a_pet1) -> CatName << endl; cout << static_cast<Dog *>(a_pet2) -> DogName << endl; // static_cast does NOT do any type check. which may cause unintended error // Interesting result: the common base class member is saved and right, the extra target subclass members are just concatenated static_cast<Cat *>(a_pet2) -> MakeSound(); // dog meow static_cast<Dog *>(a_pet1) -> MakeSound(); // cat bark static_cast<Dog *>(a_pet3) -> MakeSound(); // bird MakeSound() NOT Laugh(int) cout << static_cast<Cat *>(a_pet2) -> CatName << endl; cout << static_cast<Dog *>(a_pet1) -> DogName << endl; // Caution cout << static_cast<Dog *>(a_pet3) -> DogName << endl; // No compile time error, debug shows out of bounds // Runtime error: "Segmentation fault; core dumped;" means that you tried to access memory that you do not have access to. // Runtime stops here, no further execution due to out of bounds Dog *a_birddog = static_cast<Dog *>(a_pet3); a_birddog -> MakeSound(); Bird *a_bird = static_cast<Bird *>(a_pet3); a_bird -> Laugh(1); // dynamic_cast can downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type. // dynamic_cast<Cat *>(a_pet1) -> MakeSound(); // error: cannot dynamic_cast ‘a_pet1’ (of type ‘class Pet*’) to type ‘class Cat*’ (source type is not polymorphic) // dynamic_cast<Dog *>(a_pet2) -> MakeSound(); // error: cannot dynamic_cast ‘a_pet2’ (of type ‘class Pet*’) to type ‘class Dog*’ (source type is not polymorphic) */ // 6.3 /* Cat *a_cat; Dog *a_dog; a_cat = new Cat("Kitty"); a_dog = new Dog("Doggie"); a_cat -> MakeSound(); static_cast<Pet *>(a_cat) -> MakeSound(); a_dog -> MakeSound(); static_cast<Pet *>(a_dog) -> MakeSound(); // dynamic_cast == Implicit conversion dynamic_cast<Pet *>(a_dog) -> MakeSound(); // the Pet says: Shh! Shh! // Implicit conversion Pet *a_pet = a_cat; a_pet -> MakeSound(); // the Pet says: Shh! Shh! */ // Assessment: 70% // Q1: Compilation fails /* Y y; cout << y.v; // error: 'int X::v' is private */ // Q2: 0 is wrong, Compilation fails is right /* Y *y = new Y(); // error: 'Y::Y()' is private // Explicit Constructors have to be public // Y *y = new Y; // error: 'Y::Y()' is private cout << y->v; // error: 'int X::v' is protected delete y; */ // Q3: Compilation fails /* Z *z = new Z(); Y *y = new Y(); z = y; // error: cannot convert 'Y*' to 'Z*' in assignment cout << (z == y); // error: comparison between distinct pointer types 'Z*' and 'Y*' lacks a cast */ // Q4: Y /* X *x = new Y(); static_cast<Y *>(x) -> shout(); */ // Q5: X is wrong, Z is right // If base is virtual, all subclasses are virtual as well, no matter how many inheritance /* Y *y = new Z(); dynamic_cast<X *>(y) -> shout(); // Z y -> shout(); // Z */ // Q6: 1 /* A a; Do(a); a.inc(); cout << a.val; */ // Q7: 2 /* A a; Do(&a); cout << a.inc(); */ // Q8: 22 /* A a,b = a; cout << a.get() << b.get(); */ // Q9: Compilation fails is wrong, 33 is right /* A a(2); // There is an explicit copy constructor, no error here A b(a); cout << a.get() << b.get(); */ // Q10: 1 /* A a; B b; a.set(1); b.kill(a); cout << a.get(); */ // Assessment Retake: 100% // Q4: X /* Y *y = new Z(); dynamic_cast<X *>(y) -> shout(); */ // Q6: 220 // If no override, use the parent one, even it's virtual A *a = new C();; Do(a); return 0; }