Presentation is loading. Please wait.

Presentation is loading. Please wait.

CISC/CMPE320 - Prof. McLeod

Similar presentations


Presentation on theme: "CISC/CMPE320 - Prof. McLeod"— Presentation transcript:

1 CISC/CMPE320 - Prof. McLeod
Winter 2013 CISC/CMPE320 1/12/2019 CISC/CMPE320 Assignment 4 on using the heap is due this Friday at 7pm. Presentation schedule was announced in last Friday’s lecture. No conflicts, yet. Is there any team that would like to switch on Tuesday the 27th from the lecture time to the tutorial time (and room)? Fall 2018 CISC/CMPE320 - Prof. McLeod Prof. Alan McLeod

2 CISC/CMPE320 - Prof. McLeod
Today Look at how Inheritance and Memory Management go together in yet another demo. Two virtual function “Gotchas”. Building templated class and functions. Fall 2018 CISC/CMPE320 - Prof. McLeod

3 Back to the Shapes Example
See the Shapes hierarchy program again, using the heap. Somewhat simplified from last time. Implements the “Big Three”. Also includes the use of our own namespace just for yucks! Shape colour Rectangle fillColour, width, height Square Fall 2018 CISC/CMPE320 - Prof. McLeod

4 CISC/CMPE320 - Prof. McLeod
Shapes on the Heap Not worried about testing polymorphism this time. Shape is abstract again. Both Shape and Rectangle have an attribute on the heap. Each class has full implementations of the “Big Three”. The operator= overload in the child class shadows the one in the parent class because they are not virtual. Fall 2018 CISC/CMPE320 - Prof. McLeod

5 CISC/CMPE320 - Prof. McLeod
Shapes on the Heap, Cont. Note how the child class’ copy constructor invokes the parent class’ copy constructor. And, how the child class’ operator= invokes the parent class’ operator=. However, the child class’ destructor does not have to invoke the parent class’ destructor because they are virtual. Note the behaviour that results from deleting a pointer of a base class type that is pointing to a derived class object. Fall 2018 CISC/CMPE320 - Prof. McLeod

6 CISC/CMPE320 - Prof. McLeod
Shapes on the Heap, Cont. Note that the order of destruction is the inverse of the order of construction, as it should be. This is also a result of the destructors being virtual, and the fact that a child class’ constructor must invoke the parent class’ constructor first thing. Fall 2018 CISC/CMPE320 - Prof. McLeod

7 The “Big Three” and Inheritance
It is important to realize that constructors, destructors and operator= functions are not inherited in derived classes. If you don’t write them you will get compiler generated versions instead. The compiler’s versions will not necessarily do what you want! Fall 2018 CISC/CMPE320 - Prof. McLeod

8 The “Big Three” and Inheritance, Cont.
For example, the compiler will only make member wise copies of attributes which could result in aliasing and will not put attributes on the heap. If you don’t write a destructor for a derived class that has an attribute on the heap, then it will not get deleted. Once you write the “Big Three” in one class in a hierarchy it is safest to write them for all three classes. Fall 2018 CISC/CMPE320 - Prof. McLeod

9 Aside – Virtual Big Three?
The destructor is already virtual and it should be – to make sure that all are invoked regardless of pointer type. Could the other two be virtual? But then you run the risk of assigning or copying an object by value of one type into an object of another type, which should not be possible. Instead, keep the types consistent and use “refinement” of the functions instead. Fall 2018 CISC/CMPE320 - Prof. McLeod

10 Virtual Function “Gotchas”
The two gotchas are: When you mix overloading and overriding, and When you use default arguments in virtual functions. See virtualProblems.h. (I have also supplied implementation and testing files corresponding to this code, but will not take the time to look at them in class.) Fall 2018 CISC/CMPE320 - Prof. McLeod

11 Overloading Virtual Functions
Overloading and Overriding really don’t mix well in C++! But, suppose you *really* need to have overloaded virtual functions in a base class. Then you override one of them in a derived class. The use of the overriden function will not yield the expected results! Fall 2018 CISC/CMPE320 - Prof. McLeod

12 Overloading Virtual Functions, Cont.
One solution would be to force each derived class to override all of the overloaded virtual functions from the base class. How do you enforce this? And is it too much work for little gain? The better solution is to make the overloaded functions non-virtual and have them call normal, non-overloaded virtual functions (use inlines). A derived class can now safely override the non-overloaded virtual versions. Fall 2018 CISC/CMPE320 - Prof. McLeod

13 Default Arguments in Virtual Functions
A derived class should be able to change the default argument in the overridden version of the function. But, it turns out that the default argument is statically bound to the one provided in the base class. The default argument used is determined by the pointer type statically, not by the dynamic object type at runtime. Fall 2018 CISC/CMPE320 - Prof. McLeod

14 Default Arguments in Virtual Functions, Cont.
One solution would be to *not* use default arguments in virtual functions! But, if you must: Consider a solution like the one used for overloaded virtual functions: Make the function with the default argument non-virtual. Have it invoke a protected inline virtual that does not have a default argument. A derived class can alter the behavior by overriding the protected virtual function. Fall 2018 CISC/CMPE320 - Prof. McLeod

15 CISC/CMPE320 - Prof. McLeod
Templates - An Example Suppose you want a function that displays an array, but you don’t want to limit to just one type. Do you write overloaded versions? One each for an array of int, an array of double, an array of char, etc.? What if you want it to work for a class type, as well – suppose you had an array of strings? You don’t have a base Object type like you had in Java. The answer is to use a Template Function: Fall 2018 CISC/CMPE320 - Prof. McLeod

16 CISC/CMPE320 - Prof. McLeod
An Example, Cont. Prototype: template<typename T> void printArray(ostream&, const T[], int); When invoked, T can be any primitive type or object type. Fall 2018 CISC/CMPE320 - Prof. McLeod

17 CISC/CMPE320 - Prof. McLeod
An Example, Cont. Implementation: template<typename T> void printArray(ostream& out, const T data[], int size) { T value; out << "Array contents: " << endl; for (int i = 0; i < size; i++ ) { value = data[i]; if ((i + 1) % 10 == 0) out << value << endl; else out << value << '\t'; } Fall 2018 CISC/CMPE320 - Prof. McLeod

18 CISC/CMPE320 - Prof. McLeod
An Example, Cont. Note that you need the template<typename T> line again. T is just an arbitrary name, it can be anything you want. Note the use of T in the function – standing in for a type. Now, printArray can be invoked with any type array (assuming it works with <<). Fall 2018 CISC/CMPE320 - Prof. McLeod

19 CISC/CMPE320 - Prof. McLeod
An Example, Cont. Invoked from main: double nums[40]; for (int i = 0; i < 40; i++) nums[i] = 0.1 * i; printArray(cout, nums, 40); Fall 2018 CISC/CMPE320 - Prof. McLeod

20 Template Functions, Cont.
The way printArray is invoked here, the actual type is inferred from the argument at run time. If you have more than one parameter using the type T, they must end up being the same inferred type at runtime. An alternative is to specify the type when you invoke the function: printArray<double>(cout, nums, 40); Fall 2018 CISC/CMPE320 - Prof. McLeod

21 Template Functions, Cont.
If T will be an object type, remember to make sure that all operations carried out in the function are defined for this object. Unlike Java generics, the C++ compiler cannot check this for you. Hint: build and debug the function with a concrete type first. Error messages that result from using Templates are harder to interpret. Fall 2018 CISC/CMPE320 - Prof. McLeod

22 Templates vs. Polymorphism
Templates supply a kind of compile-time polymorphism. Normal polymorphism is strictly a run-time process. A Templated Function is a function “factory”. Functions with the necessary types are created at compilation. As a result, the use of Templates has a very low run-time cost. Fall 2018 CISC/CMPE320 - Prof. McLeod

23 CISC/CMPE320 - Prof. McLeod
Specialization Occurs when you have an overloaded, non-template version of the same templated function. If present, and the argument types match, then the non-template version will be used in preference to the template version. Fall 2018 CISC/CMPE320 - Prof. McLeod

24 CISC/CMPE320 - Prof. McLeod
Templated Classes Another example: Suppose you need a class to store a pair of anythings… Interface: template<typename F, typename S> class Pair { public: Pair(const F&, const S&); F getFirst() const; S getSecond() const; private: F first; S second; }; Fall 2018 CISC/CMPE320 - Prof. McLeod

25 CISC/CMPE320 - Prof. McLeod
Template Classes, Cont. Just for fun, we are assuming that the two things can be of different types. Note that you can have as many typenames in the template as you want. Implementation on the next slide: Fall 2018 CISC/CMPE320 - Prof. McLeod

26 CISC/CMPE320 - Prof. McLeod
template<typename F, typename S> Pair<F, S>::Pair(const F& a, const S& b) : first(a), second(b) {} F Pair<F, S>::getFirst() const { return first; } S Pair<F, S>::getSecond() const { return second; Note how the template statement has to be repeated. Fall 2018 CISC/CMPE320 - Prof. McLeod

27 CISC/CMPE320 - Prof. McLeod
Template Classes, Cont. With template classes, the type cannot be inferred, you must state it explicitly. Suppose you have a function that returns the minimum and the maximum of an array at the same time. See the next slide: Fall 2018 CISC/CMPE320 - Prof. McLeod

28 CISC/CMPE320 - Prof. McLeod
Pair<double, double> findMinMax(const double data[], const int size) { double low = data[0]; double high = data[0]; for (int i = 1; i < size; i++) { if (data[i] < low) low = data[i]; if (data[i] > high) high = data[i]; } return Pair<double, double>(low, high); Fall 2018 CISC/CMPE320 - Prof. McLeod

29 CISC/CMPE320 - Prof. McLeod
Reminder – typedef You might get tired of typing Pair<double, double> all the time! typedef Pair<double, double> PairDD; Simplifies findMinMax() a bit: Fall 2018 CISC/CMPE320 - Prof. McLeod

30 CISC/CMPE320 - Prof. McLeod
PairDD findMinMax(const double data[], const int size) { double low = data[0]; double high = data[0]; for (int i = 1; i < size; i++) { if (data[i] < low) low = data[i]; if (data[i] > high) high = data[i]; } return PairDD(low, high); Fall 2018 CISC/CMPE320 - Prof. McLeod

31 CISC/CMPE320 - Prof. McLeod
Templates, Cont. You can also add non-type arguments to a template. Suppose you wanted to specify the size of an array to be used as T: template<typename T, int SIZE> When used, you would have to supply a type for T and an int for the second argument: AClass<double, 10> aVar; Fall 2018 CISC/CMPE320 - Prof. McLeod

32 CISC/CMPE320 - Prof. McLeod
Templates, Cont. You can also use an argument to specify a policy. For example, the first argument is the name of an object to be sorted, the second is the name of a class that supplies the desired sort criteria for that object. Template types ignore object extension, so T can only be one type, not a derived type. If you place restrictions on what T can be, you should document them in a comment. Fall 2018 CISC/CMPE320 - Prof. McLeod


Download ppt "CISC/CMPE320 - Prof. McLeod"

Similar presentations


Ads by Google