COMP6771 Advanced C++ Programming

Similar documents
COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

Overview of C++: Part 1

Introduction to C++ Introduction to C++ Dr Alex Martin 2013 Slide 1

What is Polymorphism? Quotes from Deitel & Deitel s. Why polymorphism? How? How? Polymorphism Part 1

Slide Set 14. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

CS250 Intro to CS II. Spring CS250 - Intro to CS II 1

Polymorphism Part 1 1

Chapter 15. Object-Oriented Programming

CS250 Final Review Questions

class Polynomial { public: Polynomial(const string& N = "no name", const vector<int>& C = vector<int>());... };

Week 7. Statically-typed OO languages: C++ Closer look at subtyping

C++ Addendum: Inheritance of Special Member Functions. Constructors Destructor Construction and Destruction Order Assignment Operator

19. Classes. Encapsulation: public / private. Member Functions: Declaration. Member Functions: Call. class rational { int n; int d; // INV: d!

COMP6771 Advanced C++ Programming

Special Member Functions

C++ Programming: Polymorphism

VIRTUAL FUNCTIONS Chapter 10

PIC10B/1 Winter 2014 Exam I Study Guide

Special Member Functions. Compiler-Generated Destructor. Compiler-Generated Default Constructor. Special Member Functions

21. Dynamic Datatypes and Memory Management

COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming

The issues. Programming in C++ Common storage modes. Static storage in C++ Session 8 Memory Management

21. Dynamic Datatypes and Memory Management

Increases Program Structure which results in greater reliability. Polymorphism

COMP 2355 Introduction to Systems Programming

Instantiation of Template class

Networked Embedded System Patterns for C Developers. Overview of C (& C++) Programming Styles. Douglas C. Schmidt

Structuur van Computerprogramma s 2

Object-Oriented Languages and Object-Oriented Design. Ghezzi&Jazayeri: OO Languages 1

CS32 Summer Intro to Object-Oriented Programming in C++ Victor Amelkin August 12, 2013

Inheritance, Polymorphism and the Object Memory Model

Data Structures and Other Objects Using C++

C++ Inheritance and Encapsulation

Intro to OOP Visibility/protection levels and constructors Friend, convert constructor, destructor Operator overloading a<=b a.

OBJECT ORIENTED PROGRAMMING USING C++ CSCI Object Oriented Analysis and Design By Manali Torpe

Dynamic Binding C++ Douglas C. Schmidt

Interview Questions of C++

ECE 3574: Dynamic Polymorphism using Inheritance

See the CS 2704 notes on C++ Class Basics for more details and examples. Data Structures & OO Development I

Common Misunderstandings from Exam 1 Material

17. Classes. Encapsulation: public / private. Member Functions: Declaration. Member Functions: Call. class rational { int n; int d; // INV: d!

ECE 2400 Computer Systems Programming Fall 2017 Topic 14: C++ Inheritance

Object-Oriented Concept

Outline. Java Models for variables Types and type checking, type safety Interpretation vs. compilation. Reasoning about code. CSCI 2600 Spring

Object-Oriented Programming

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

Chapter 11. Abstract Data Types and Encapsulation Concepts

CS

Inheritance. OOP components. Another Example. Is a Vs Has a. Virtual Destructor rule. Virtual Functions 4/13/2017

Object Oriented Software Design II

Inheritance and Polymorphism

Part III. Advanced C ++

THE PROGRAMMING RESEARCH GROUP

Object Oriented Software Design II

OOPS Viva Questions. Object is termed as an instance of a class, and it has its own state, behavior and identity.

CSCI-1200 Data Structures Fall 2017 Lecture 25 C++ Inheritance and Polymorphism

C++ Mini-Course. Part 1: Mechanics Part 2: Basics Part 3: References Part 4: Const Part 5: Inheritance Part 6: Libraries Part 7: Conclusion. C Rulez!

C++ Templates. David Camp

double d0, d1, d2, d3; double * dp = new double[4]; double da[4];

Lecture 5: Inheritance

Cpt S 122 Data Structures. Course Review Midterm Exam # 2

IS 0020 Program Design and Software Tools

Object Oriented Programming

Java Object Oriented Design. CSC207 Fall 2014

Object Oriented Design Final Exam (From 3:30 pm to 4:45 pm) Name:

Inheritance and Polymorphism

Part VII. Object-Oriented Programming. Philip Blakely (LSC) C++ Introduction 194 / 370

04-24/26 Discussion Notes

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

CS 376b Computer Vision

Object-oriented Programming. Object-oriented Programming

An Overview of C++ Douglas C. Schmidt

INSTRUCTIONS TO CANDIDATES

CMSC131. Inheritance. Object. When we talked about Object, I mentioned that all Java classes are "built" on top of that.

CSCI-1200 Computer Science II Fall 2006 Lecture 23 C++ Inheritance and Polymorphism

Programmazione. Prof. Marco Bertini

Fast Introduction to Object Oriented Programming and C++

Computer Science II CSci 1200 Lecture 24 C++ Inheritance and Polymorphism

What s Conformance? Conformance. Conformance and Class Invariants Question: Conformance and Overriding

CS32 - Week 1. Umut Oztok. June 24, Umut Oztok CS32 - Week 1

September 19,

CS 2150 Exam 1, Spring 2018 Page 1 of 6 UVa userid:

Polymorphism. Zimmer CSCI 330

Copying Data. Contents. Steven J. Zeil. November 13, Destructors 2

What will happen if we try to compile, link and run this program? Do you have any comments to the code?

Chapter 3. Object-Based Programming Part I

CSE 333. Lecture 11 - constructor insanity. Hal Perkins Paul G. Allen School of Computer Science & Engineering University of Washington

C++ Mini-Course. Part 1: Mechanics Part 2: Basics Part 3: References Part 4: Const Part 5: Inheritance Part 6: Libraries Part 7: Conclusion. C Rulez!

Data types. Definitions Aggregate constructors User-defined type definitions Types and storage Types and subtypes Type systems and type checking

Part X. Advanced C ++

CMSC 202 Final May 19, Name: UserID: (Circle your section) Section: 101 Tuesday 11: Thursday 11:30

CSE 303: Concepts and Tools for Software Development

CS105 C++ Lecture 7. More on Classes, Inheritance

C++ (Non for C Programmer) (BT307) 40 Hours

Transcription:

1 COMP6771 Advanced C++ Programming Week 11 Object Oriented Programming 2016 www.cse.unsw.edu.au/ cs6771

2 Covariants and Contravariants Let us assume that Class B is a subtype of class A. Covariants: What should return types of overriding function be? All member functions of B must return the same or a narrower set of types as A The return type is said to be covariant Contravariants: What should parameter types of overriding function be? All member functions of B must take the same or a broader set of arguments compared with the member functions of A The argument type is said to be contravariant. Return types are covariant but argument types are contravariant

3 Overriding Virtuals in Derived Classes Virtual functions are inherited but typically overridden: class A { virtual A f(int i, int j); } class B : public A { virtual B f(int i, int j); } The overriding f must have the same signature, and the return type B must be A or a derived class of A (i.e., covariant).

4. Covariant Return Types Changing a method s return type when overriding it in a derived class 1 class Shape { 2 public: 3 virtual void draw() = 0; 4 virtual Shape* clone() const = 0; 5 }; 6 class Circle : public Shape { 7 void draw() { /* draw a circle */ } 8 virtual Circle* clone() const { return new Circle(this*); } 9 }; 10 class Square: public Shape { 11 void draw() { /* draw a square */ 12 virtual Square * clone() const { return new Square(this*); } 13 }; Benefit: Circle c1; Circle *c2 = c1.clone(); // down-casting required if clone had returned a shape* Shape *s = c1.clone(); // ok: covariant // will contravariant return types work?

5 Default Arguments and Virtuals 1 struct B { 2 virtual void foo(int i = 1) { 3 std::cout << "B: " << i; 4 } 5 }; 6 7 struct D : public B { 8 void foo(int i = 2) { 9 std::cout << "D: " <<i; 10 } 11 }; 12 13 int main(void) { 14 B *p = new D(); 15 p->foo(); 16 } Output: D: 1 Default arguments determined based on static type of p The function call resolved using dynamic type of p Why? Efficiency since the compiler doesn t need to generate code used to determine at run time which default to use

6 Initialisation and Destruction Initialisation order: class Book {...}; class Disc book: public Book {...}; class Bulk Disc book : public Disc book {...}; Bulk Disc_book dmb; dmb Subobjects (1) Book (2) Disc book (3) Bulk Disc book Within each subobject from a class: 1. the data members initialised in declaration order 2. the class constructor is called The direct base constructor of a class is always called first Destruction: (the reverse) 1 for each sub-obj from the most to the least derived 2 call its destructor 3 Call its members dtors in reverse declaration order

7 Member Initialisation List Design requirements of a derived class s constructor Call an appropriate immediate base constructor Initialise its own members Conventions:.1 The base class s constructor is listed first.2 The member constructors are in the order of declaration class Disc_book : public Book {... Disc_book(const std::string &book_isbn = "", double sales_price, std::size_t qty = 0, double dist_rate = 0.0) : Book(book_isbn, sales_price), min_qty(0), discount (0.0) { } }; If a base constructor is not called by programmer, the compiler will call the default one and scream if it does not exist

Virtual Destructors The destructor in Book is virtual Disc_book *p = new Disc_book(); delete p; // dynamic binding // call the destructor in Disc_book If the destructor in Book is nonvirtual Book *p = new Disc_book(); delete p; // static binding // call the destructor in Book The virtual destructor in Book must be defined since it will be called by the destructor in the least derived class 8 There are no virtual constructors since dynamic binding cannot be realised on an object that is not yet fully constructed. No move operation synthesised once a destructor is defined

9 Move Operations vs. Virtual Destructors If a class defines a virtual destructor, then it doesn t get synthesised move operations. Neither do its derived classes. Must define your own if needed: 1 class Book { 2 Book(Book &&) = default; 3 Book& operator=book(book &&) = default; 4 } Use your own if the default is not suitable

10 Virtuals in Constructors and Destructors If a virtual member function is called insider a constructor or destructor, then the version invoked is the one defined for the type of the constructor or destructor itself 1 class A { 2 public: 3 virtual void f() { std::cout << "f in B" << std::endl; } 4 }; 5 6 class B : public A { 7 public: 8 B() { f(); } 9 void f() { std::cout << "f in B" << std::endl; } 10 B() { f(); } 11 }; 12 13 class C : public B { 14 public: 15 void f() { std::cout << "f in C" << std::endl; } 16 }; 17 18 int main() { 19 C c; 20 A &a = c; 21 a.f(); 22 } What is the output?

11 Virtuals in Constructors and Destructors If a virtual member function is called insider a constructor or destructor, then the version invoked is the one defined for the type of the constructor or destructor itself 1 class A { 2 public: 3 virtual void f() { std::cout << "f in B" << std::endl; } 4 }; 5 6 class B : public A { 7 public: 8 B() { f(); } 9 void f() { std::cout << "f in B" << std::endl; } 10 B() { f(); } 11 }; 12 13 class C : public B { OUTPUT 14 public: f in B 15 void f() { std::cout << "f in C" << std::endl; } f in C 16 }; f in B 17 18 int main() { 19 C c; 20 A &a = c; 21 a.f(); 22 } A constructed B constructed C destructed

12 OO Implementation of a Stack Stack Abstract Base Class (ABC): 1 class Stack { 2 public: 3 virtual Stack() { }; //virtual dtor 4 virtual void push (const int &) = 0; 5 virtual void pop () = 0; 6 virtual int& top () = 0; 7 virtual const int& top () const = 0; 8 virtual bool empty () const = 0; 9 virtual bool full () const = 0; 10 11 void operator=(const Stack&) = delete; 12 }; Move operations can be provided as explained earlier in the course

13 Why Deleted Operator= in an ABC? 1 B_Stack s1; 2 UB_Stack s2; 3 foo(s1, s2); 4 5 void foo(stack &s1, Stack &s2) { 6 s1 = s2; 7 } s1 = s2 makes no sense if s1 and s2 are different stack objects (perhaps for this particular application) Making operator= deleted or protected causes a compile-time error

14 1 #ifndef B_STACK_HPP 2 #define B_STACK_HPP 3 4 #include "Stack.hpp" 5 A Bounded stack: B stack.hpp 6 class B_Stack : public Stack { 7 public: 8 B_Stack (unsigned size_ = 10); 9 B_Stack (const B_Stack &); 10 B_Stack (); 11 B_Stack& operator=(const B_Stack &); 12 virtual void push (const int &); 13 virtual void pop (); 14 virtual int& top (); 15 virtual const int& top () const; 16 virtual bool empty () const; 17 virtual bool full () const; 18 private: 19 unsigned top_, size_; 20 int *stack_; 21 }; 22 23 #endif

15 A Bounded stack: B stack.cpp 1 #include "B_Stack.hpp" 2 3 B_Stack::B_Stack (unsigned s) 4 : top_{0}, size_{s}, stack_{new int[s]} { } 5 6 B_Stack:: B_Stack () { delete [] stack_; } 7 8 inline void B_Stack::push(const int &) { 9 stack_[top_++] = ; 10 } 11 12 inline void B_Stack::pop() { --top_; } 13 14 inline int& B_Stack::top() { return stack_[top_-1]; } 15 inline const int& B_Stack::top() const 16 { return stack_[top_-1]; } 17 18 inline bool B_Stack::empty() const { 19 return top_ == 0; 20 }

16 A Bounded stack: B stack.cpp 1 inline bool B_Stack::full() const { return top_ == size_; } 2 3 B_Stack::B_Stack(const B_Stack &s) 4 : top_(s.top_), 5 size_(s.size_), 6 stack_(new int[s.size_]) { 7 for (unsigned i = 0; i < s.size_; i++) 8 stack_[i] = s.stack_[i]; 9 } 10 11 B_Stack& B_Stack::operator=(const B_Stack &s) { 12 if (this!= &s) { 13 delete [] stack_; 14 top_ = s.top_; 15 size_ = s.size_; 16 stack_ = new int[s.size_]; 17 for (unsigned i = 0; i < s.top_; i++) 18 stack_[i] = s.stack_[i]; 19 } 20 return *this; 21 }

17. An Unbounded stack: UB stack.hpp 1 #ifndef UB_Stack_HPP 2 #define UB_Stack_HPP 3 4 #include "Stack.hpp" 5 6 class UB_Stack : public Stack { 7 public: 8 UB_Stack () { head_ = nullptr; } 9 UB_Stack(const UB_Stack &); 10 UB_Stack (); 11 UB_Stack& operator=(const UB_Stack &s); 12 virtual void push (const int &); 13 virtual void pop (); 14 virtual int& top (); 15 virtual const int& top () const; 16 virtual bool empty () const { return head_ == nullptr; } 17 virtual bool full () const { return false; }; 18 private: 19 class Node; 20 void reverse (Node *); 21 Node *head_; 22 }; 23 24 #endif

18. An Unbounded stack: UB Stack.cpp 1 #include "UB_Stack.hpp" 2 3 class UB_Stack::Node { 4 friend class UB_Stack; 5 Node (int i, Node *n = 0) : _{i}, _{n} { } 6 Node() { delete _; } 7 int _; 8 Node *_; 9 }; 10 11 UB_Stack::UB_Stack(const UB_Stack &s) { 12 head_ = nullptr; 13 reverse(s.head_); 14 } 15 16 UB_Stack:: UB_Stack() { 17 delete head_; 18 } 19 20 UB_Stack& UB_Stack::operator=(const UB_Stack &s) { 21 if (this!= &s) { 22 delete head_; 23 reverse(s.head_); 24 return *this; 25 } 26 }

19. An Unbounded stack: UB stack.cpp 1 void UB_Stack::push(const int &) { 2 Node *t = new Node (, head_); head_ = t; 3 } 4 5 void UB_Stack::pop() { 6 Node *t = head_; 7 head_ = head_->_; 8 t->_ = nullptr; 9 delete t; 10 } 11 12 inline int& UB_Stack::top() { 13 return head_->_; 14 } 15 16 inline const int& UB_Stack::top() const { 17 return head_->_; 18 } 19 20 void UB_Stack::reverse(Node *h) { 21 if (h!= nullptr) { 22 reverse(h->_); 23 push(h->_); 24 } 25 }

20 Client Code 1 #include "Stack.hpp" 2 3 void foo(stack *stack) { 4 int i = 1927; 5 stack->push(6771); 6 stack->push(i); 7 stack->pop(); 8 std::cout << s->top(); 9 //... 10 } Using our abstract base class, it is possible to write code that does not depend on the stack implementation.

21 Create Some Stack Objects Of course, someone else has to create a concrete stack: 1 #include "B_Stack.hpp" 2 #include "UB_Stack.hpp" 3 4 extern void foo(stack *); 5 6 Stack* make_stack (bool use_b_stack) { 7 if (use_b_stack) 8 return new B_Stack; 9 else 10 return new UB_Stack; 11 } 12 13 int main(void) { 14 foo(make_stack (false)); 15 } Needs recompilation if B Stack/UB Stack has changed

22 OO in C++ Polymorphism/dynamic binding achieved with virtual functions A class with virtual functions (declared or inherited) is also said to be polymorphic since it exhibits multiple behaviours due to the multiple implementations of virtual functions in derived classes Combining ABCs and dynamic binding to separate an application s interface from its implementation

23 Copy Control The Big Three/Five: (Virtual) Destructor Copy constructor Copy Assignment Move constructor Move Assignment Need only to provide these for your derived classes (since a base class has been provided with these by its designer In general, classes with pointer members need to define their own copy control to manage these members The semantics for the compiler-synthesised control-control: memberwise copy, move, assignment and destroy

24 Virtual Destructors Essential when you apply delete to pointers/references to base classes: stack *p = new UB_Stack;... delete p; If ~stack is nonvirtual, then static binding will cause stack::~stack to be invoked, resulting in memory leaks! Should generally declare your destructor virtual if the class is intended to be used as a base class Destructors cannot be pure virtual See Item 14, Meyers Effective C++

Compiler-Generated (Default) Copy Constructor semantics: memberwise copy class Derived : public Base { A1 o1 A2 o2... } The default: Derived::Derived (const Derived &d) : call Base s copy constructor, call A1 s copy constructor, call A2 s copy constructor,... { } 25

26 Compiler-Generated Copy Constructors for B Stack Shallow copy: B_Stack::B_Stack(const B_Stack &s) { top_ = s.top_; size_ = s.size_; stack_ = s.stack_; } Example: B_Stack s1(3); s1.push(1); Runtime Stack s1.push(2); B_Stack s2 = s1; // same as B_Stack s2(s1); s1 s2 2 3 2 3 Heap 1 2

27 Our Copy Constructor (Value Semantics) Deep copy: B_Stack::B_Stack(const B_Stack &s) : top_ (s.top_), size_(s.size_), stack_(new int[s.size_]) { for (unsigned i = 0; i < s.size_; i++) stack_[i] = s.stack_[i]; } Example: B_Stack s1(3); s1.push(1); s1.push(2); B_Stack s2 = s1; s1 s2 2 3 2 3 1 2 1 2 Heap

28 Copy Constructor for UB Stack Shallow copy: UB_Stack::UB_Stack(const UB_Stack &s) : head_(s.head_) {} Example: UB_Stack s2 = s1; // copy construction s1 head s2 head runtime stack heap

Our Copy Constructor for UB stack Deep copy: UB_Stack::UB_Stack(const UB_Stack &s) { head_ = nullptr; reverse(s.head_); } Example: UB_Stack s2 = s1; // copy construction s1 head s2 head 29 runtime stack heap

Compiler-Generated (Default) Assignment Operator semantics: memberwise assignment class Derived : public Base { A1 o1 A2 o2... } The default: Derived::Derived (const Derived &d) { copy Base s assignment operator call A1 s assignment operator call A2 s assignment operator... } 30

Compiler-Generated Operator= for B stack 31 Shallow copy: B_Stack& operator=(const B_Stack &s) { if (this!= &s) { top_ = s.top_; size_ = s.size_; stack_ = s.stack_; } return *this; } Example: B_Stack s1(3), s2(2); s1.push(1); s1.push(2); (A) s2 = s1; (B) s1 s2 2 3 0 2 (A) Heap 1 2?? s1 s2 2 3 2 3 (B) Heap 1 2?? leaks!

Our Operator= for B stack 32 Deep copy: B_Stack& B_Stack::operator=(const B_Stack &s) { if (this!= &s) { delete [] stack_; top_ = s.top_; size_ = s.size_; stack_ = new int[s.size_]; for (unsigned i = 0; i < s.top_; i++) stack_[i] = s.stack_[i]; } return *this; } } Example: B_Stack s1(3), s2(2); s1.push(1); s1.push(2); (A) s2 = s1; (B) s1 s2 2 3 0 2 (A) Heap 1 2?? freed! s1 s2 2 3 2 3 (B) Heap 1 2 1 2

33 Compiler-Generated Operator= for UB stack Shallow copy: UB_Stack& UB_Stack::operator=(const UB_Stack &s) { head_ = s.head_; return *this; } Example: s2 = s1; s1 head s2 head runtime stack heap

Our Operator= for UB stack Deep copy: UB_Stack& UB_Stack::operator=(const UB_Stack &s) { if (this!= &s) { delete head_; reverse(s.head_); } return *this; } Example: s2 = s1; s1 head s2 head 34 runtime stack heap

35 Readings Chapter 15 of the text Chapter 12, Stroustrup s book (Derived Classes)