CIS 3142 Advice — Chapter 1

CISC 3142
Programming Paradigms in C++
Part 1 — Introduction
Chapter 3 — A Tour of C++: Abstraction Mechanisms

Reading from the Text

Chapter 3 — A Tour of C++ : Abstraction Mechanisms

Overview

Introduction of the two basic abstraction mechanisms in the language: classes (for modelling) and templates (for generic behavior)

Topics

Classes

Concrete Types
Abstract Types
An abstract (data) type (ADT) is a data type in which the set of legal values and associated operations are specified, while the manner in which they are carried out is left unspecified.

      • This is accomplished via pure virtual functions.
    class Stack {
    public:
    	virtual void push(int) = 0;
    	virtual void pop() = 0;
    	virtual bool isEmpty() = 0;
    };
    		
Virtual Function
  • One must declare (in the base class) the possibility of overriding a function, using the virtual keyword
    class B {
    public:
    	…
    	virtual void f();	// expects/permits a derived class to override f polymorphically ally (i.e., with dynamic function resolution)
    	…
    };
    		
  • without virtual function resolution remains static
  • In the above example, B would be expected to have its pwn implementation (i.e., function body) for f
  • alternatively, one could make f abstract at the level of B by declaring it a pure virtual function
    	virtual void f() = 0;
    		
    • B then becomes an abstract class, and no objects can be declared/created of type B
    • however, pointers/references to B can be declared and objects of derived classes (in which f has been defined) can be upcast to such a reference.
Class Hierarchies

Copy/Move

Resources
  • as defined before, a resource is anything of a limited nature
  • resources must be properly handled in the context of copying (forming aliases)
  • containers as resource handles
    • the container contains a pointer to a dynamically allocated resource (array, I/O stream, etc)
    • constructors, destructors, copy, and move operations provide support for this

Templates

Here is a writeup on templates
Parameterized Types (Class Templates)
template <typename T>
class Pair {
public:
	Pair(T f, T s) : first(f), second(s) {}	// member initialization list — Preferred to assigning in the body
	T getFirst() {return first;}
	T getSecond() {return second;}
	void swap() {
		T temp = first;
		first = second;
		second = temp;
	}
private:
	T first, second;
};
…
Pair<int> pi(2, 3);
Pair<string> ps("Hello", "Goodbye");
Function Templates
Function Object (Functor)
  • class whose main purpose is to provide a member function to be invoked in a generic algorithm
    • an object of the class would then be passed to the generic algorithm to supply the type-specific semantics defined in the method
  • Consider the following template for bubble sort:
    template <typename T>
    void sort(T arr[], int n) {
    	for (int last = n-1; i > 0; i--)
    		for (int i = 0; i < last; i++)
    			if (arr[i] > arr[i+1]) {
    				T temp = arr[i];
    				arr[i] = arr[i+1];
    				arr[i+1]= temp;
    			}
    }
    		
    • The 'weak' point is the > operator for the (as yet unspecified type T)
      • We could restrict the sort instantiation to types having such an operator
      • or we could pass such an operator in to the sort:
        template <typename T>
        void sort(T arr[], int n, ??? gt) {
        	for (int last = n-1; i > 0; i--)
        		for (int i = 0; i < last; i++)
        			if (gt(arr[i], arr[i+1])) {
        				T temp = arr[i];
        				arr[i] = arr[i+1];
        				arr[i+1]= temp;
        			}
        }
        						
      • The representation of that function is a functor
    • In Java, this would typically be represented by an interface with a single method
      interface Comparator {
      	int compare(Object obj1, Object obj2);
      }
      
      void sort(Object [] arr, Comparator comparator) {
      	for (int last = arr.length-1; i > 0; i--)
      		for (int i = 0; i < last; i++)
      			if (comparator.compare(arr[i], arr[i+1] == 1) {
      				Object temp = arr[i];
      				arr[i] = arr[i+1];
      				arr[i+1]= temp;
      			}
      }
      		
      class Employee {
      …
      	String getName() {…};
      	int getID() {…};
      …
      }
      
      Employee [] employees = new …
      
      class IDComparator implements Comparator {
      	int compare(Object obj1, Object obj2) {
      		Employee e1 = (Employee)obj1;
      		Employee e2 = (Employee)obj2;
      		return e1.getID().compareTo(e2.getID());
      	}
      }
      class NameComparator implements Comparator {
      	int compare(Object obj1, Object obj2) {
      		Employee e1 = (Employee)obj1;
      		Employee e2 = (Employee)obj2;
      		return e1.getName().compareTo(e2.getName());
      	}
      }
      
      sort (employees, new NameComparator());
      …
      sort (employees, new IDComparator());
      	
    • C++ provides a more intuitive (but somewhat more complex) mechanism for specifying functors

Advice

Chapter 3 - A Tour of C++: Abstraction Mechanisms