adapted from Jean-Paul Rigault courses 1 A <Basic> C++ Course 8 Object-oriented programming 2 Julien Deantoni
2 Outline Dynamic Typing Truncature Cast
3 Variants of class Paragraph Definition of derived classes (1) We wish to have several sorts of paragraphs titles, sections, enumerations, items... We want to share as much as possible the common properties contents as a string possibility to (crude lay out) But specific properties should be possible numbering, bullets... page layout
4 Variants of class Paragraph Definition of derived classes (5) A derived class may add new properties data members member-functions friend functions A derived class may redefine (override) some inherited memberfunctions Derivation depth is unlimited Single and multiple inheritance Single: only one base class Multiple: several distinct base classes
If (int, int) is NON virtual 5
Paragraph::Paragraph(std::string title std::string content) { _title = title; _content = content; } If (int, int) is NON virtual 6
content depth Paragraph::Paragraph(std::string title std::string content) { _title = title; _content = content; } If (int, int) is NON virtual 7
Paragraph::Paragraph(std::string title std::string content) { _title = title; _content = content; } If (int, int) is NON virtual 8
Item_Paragraph::Item_Paragraph(string title, string content, char b) :Paragraph(title,content) { _bullet = b; } If (int, int) is NON virtual and is not redefined in Item_Paragraph 9
ip:item_paragraph content depth Item_Paragraph::Item_Paragraph(string title, string content, char b) :Paragraph(title,content) { _bullet = b; } If (int, int) is NON virtual and is not redefined in Item_Paragraph 10
ip:item_paragraph content depth Bullet Item_Paragraph::Item_Paragraph(string title, string content, char b) :Paragraph(title,content) { _bullet = b; } If (int, int) is NON virtual and is not redefined in Item_Paragraph 11
ip:item_paragraph Bullet Item_Paragraph::Item_Paragraph(string title, string content, string b) :Paragraph(title,content) { _bullet = b; } If (int, int) is NON virtual and is not redefined in Item_Paragraph 12
ip:item_paragraph Bullet='#' Item_Paragraph::Item_Paragraph(string title, string content, string b) :Paragraph(title,content) { _bullet = b; } If (int, int) is NON virtual and is not redefined in Item_Paragraph 13
ip:item_paragraph Bullet='#' If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 14
ip:item_paragraph Bullet='#' p.(); ip.(); If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 15
ip:item_paragraph Bullet='#' p.(); ip.(); What if we create a vector of Paragraphs?? If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 16
vp:vector ip:item_paragraph Bullet='#' vector<paragraph> vp; If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 17
vp:vector pbis:paragraph ip:item_paragraph Bullet='#' vector<paragraph> vp; vp.push_back(p); If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 18
vp:vector pbis:paragraph iptrunc:paragraph ip:item_paragraph Bullet='#' vector<paragraph> vp; vp.push_back(p); vp.push_back(ip); If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 19
vp:vector pbis:paragraph iptrunc:paragraph ip:item_paragraph Bullet='#' vector<paragraph> vp; vp.push_back(p); vp.push_back(ip); We lost the specificities of Item_Paragraph If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 20
vp:vector pbis:paragraph iptrunc:paragraph ip:item_paragraph Bullet='#' vector<paragraph> vp; vp.push_back(p); vp.push_back(ip); We lost the specificities of Item_Paragraph... Forever! If (int, int) is NON virtual and is REDEFINED in Item_Paragraph 21
vptr_p:vector ip: Item_Paragraph Bullet='#' vector<paragraph*> vptr_p What happens if we create a vector of paragraph pointer? If (int, int) is NON VIRTUAL and is redefined in Item_Paragraph 22
vptr_p:vector :paragraph* :paragraph* ip: Item_Paragraph Bullet='#' vector<paragraph*> vptr_p vptr_p.push_back(&p); vptr_p.push_back(&ip); If (int, int) is NON VIRTUAL and is redefined in Item_Paragraph 23
vptr_p:vector :paragraph* :paragraph* ip: Item_Paragraph Typed by Paragraph content depth Bullet='#' vector<paragraph*> vptr_p vptr_p.push_back(&p); vptr_p.push_back(&ip); A call to a non-virtual function is resolved according to the static type of the hidden parameter If (int, int) is NON VIRTUAL and is redefined in Item_Paragraph 24
Paragraph vtable p.(); If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 25
Paragraph vtable ip:item_paragraph Bullet='#' Item_Paragraph vtable p.(); ip.(); If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 26
Paragraph vtable ip:item_paragraph Bullet='#' Item_Paragraph vtable p.(); ip.(); What happens if we create a vector of Paragraphs?? If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 27
vp:vector pbis: Paragraph Paragraph vtable iptrunc:paragraph ip:item_paragraph Bullet='#' Item_Paragraph vtable vector<paragraph> vp; vp.push_back(p); vp.push_back(ip); We lost the specificities of Item_Paragraph If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 28
vptr_p:vector Paragraph vtable ip:item_paragraph Bullet='#' Item_Paragraph vtable vector<paragraph*> vptr_p What happens if we create a vector of paragraph pointer? If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 29
vptr_p:vector :paragraph* Paragraph vtable ip:item_paragraph Bullet='#' Item_Paragraph vtable vector<paragraph*> vptr_p vptr_p.push_back(&p); If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 30
vptr_p:vector :paragraph* :paragraph* Paragraph vtable ip:item_paragraph Bullet='#' A call to a virtual function is resolved according to the type dynamic type of the hidden parameter Item_Paragraph vtable vector<paragraph*> vptr_p vptr_p.push_back(&p); vptr_p.push_back(&ip); If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 31
vptr_p:vector :paragraph* :paragraph* :paragraph* ip:item_paragraph Bullet='#' :Paragraph Paragraph vtable Item_Paragraph vtable vector<paragraph*> vptr_p vptr_p.push_back(&p); vptr_p.push_back(&ip); vptr_p.push_back(new Paragraph(ip)); If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 32
vptr_p:vector :paragraph* :paragraph* :paragraph* ip:item_paragraph Bullet='#' :Paragraph Paragraph vtable Item_Paragraph vtable vector<paragraph*> vptr_p vptr_p.push_back(&p); vptr_p.push_back(&ip); vptr_p.push_back(new Paragraph(ip)); You have to use the clone() virtual function (course 8-OO.pdf) If (int, int) is VIRTUAL and is REDEFINED in Item_Paragraph 33
34 Abstract classes and pure virtual functions Object is abstract It cannot be instantiated Some of its behaviors cannot be defined at least one of its member function is a pure virtual function
35 Abstract classes and pure virtual functions Object is abstract It cannot be instantiated Some of its behaviors cannot be defined at least one of its member function is a pure virtual function pure virtual functions
36 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A
37 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new B(); // OK pa:a* :B f()
38 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new B(); // OK pa >f(); pa:a* :B f()
39 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new B(); // OK pa >f(); // KO Typed by pa:a* A :B f()
40 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new B(); // OK pa >f(); // KO ((B*)pa) >f(); // OK casted and then typed by (B*)pa:B* pa:a* B f() :B f()
41 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new A(); // OK pa >f(); // KO ((B*)pa) >f(); // OK casted and then typed by (B*)pa:B* pa:a* :B f() :B :A f() Unsafe!!
42 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A B* pa = new A(); // KO pa:b* pa:a* :B :A f()
43 Safe downward cast (1) Downward cast may be dangerous class A {... }; class B : public A { void f() {... } }; // f() not defined in A A* pa = new B(); // OK pa >f(); // KO ((B*)pa) >f(); // OK casted and then typed by pa:a* :B :B f() static_cast<b*>(pa) >f();// OK Unsafe!!
44 Safe downward cast (2) Operator dynamic_cast B *pb = dynamic_cast<b*>(pa); if (pb!= nullptr) { pb >f(); // OK and safe }
45 Safe downward cast (2) Operator dynamic_cast B *pb = dynamic_cast<b*>(pa); if (pb!= nullptr) pb >f(); // OK and safe try { dynamic_cast<b*>(pa) >f(); } catch(bad_cast) { cerr << "bad conversion" << endl; }
46 Safe downward cast (3) Limitation of dynamic_cast Work only on classes with virtual functions (polymorphic types) Invoking dynamic_cast from a constructor or a destructor dynamic_cast behaves like a virtual function it is statically bound in a constructor or a destructor