You are on page 1of 40

Today:

wrap up presentation of inheritance and templates


material for final exam ends
advanced inheritance and templates
other stuff
1
Kevin Sanft UCSB CS32 Summer 2010 Lecture 17
inheritance
2
Employee
protected:
int eID;
string name;
Address addr;
SalaryEmployee
void printPayStub()
HourlyEmployee
void printPayStub()
inheritance: constructors
constructors called starting from base class,
then derived class
recursive: if A is base class, B subclass of A, and
C is subclass of B, then when creating an object
of type C order of construction is A, then B, then
C

never virtual

need complete information (need to know the
exact type) to construct an object => not virtual
3
inheritance: constructors
example
4
class MyBase {
public:
MyBase() {
cout << "in MyBase() constructor\n";
}
MyBase(int x) : data(x) {
cout << "in MyBase(int) constructor\n";
}
void setData(int theData) { data=theData; }
protected:
int data;
};

class MyChild : public MyBase {
public:
MyChild() {
cout << "in MyChild() constructor\n";
}
MyChild(int x) {
data=x;
cout << "in MyChild(int) constructor\n";
}
};
cout << "\ncreate MyBase base1:\n";
MyBase base1;

cout << "\ncreat MyChild mc:\n";
MyChild mc;

cout << "\ncreate MyBase* MyChild():\n";
MyBase* mbPtr=new MyChild();

cout << "\ncreate MyBase* MyChild(4):\n";
MyBase* mbPtr2=new MyChild(4);

$ a.out

create MyBase base1:
in MyBase() constructor

creat MyChild mc:
in MyBase() constructor
in MyChild() constructor

create MyBase* MyChild():
in MyBase() constructor
in MyChild() constructor

create MyBase* MyChild(4):
in MyBase() constructor
in MyChild(int) constructor

inheritance: constructors
example
5
class MyBase {
public:
MyBase() {
cout << "in MyBase() constructor\n";
}
MyBase(int x) : data(x) {
cout << "in MyBase(int) constructor\n";
}
void setData(int theData) { data=theData; }
protected:
int data;
};

class MyChild : public MyBase {
public:
MyChild() {
cout << "in MyChild() constructor\n";
}
MyChild(int x) : MyBase(x) {
cout << "in MyChild(int) constructor\n";
}
};
cout << "\ncreate MyBase base1:\n";
MyBase base1;

cout << "\ncreat MyChild mc:\n";
MyChild mc;

cout << "\ncreate MyBase* MyChild():\n";
MyBase* mbPtr=new MyChild();

cout << "\ncreate MyBase* MyChild(4):\n";
MyBase* mbPtr2=new MyChild(4);

$ a.out

create MyBase base1:
in MyBase() constructor

creat MyChild mc:
in MyBase() constructor
in MyChild() constructor

create MyBase* MyChild():
in MyBase() constructor
in MyChild() constructor

create MyBase* MyChild(4):
in MyBase(int) constructor
in MyChild(int) constructor

inheritance: destructors
ALWAYS virtual
if not, a base type pointer that points to a derived
class would call the base type destructor only
potentially leaving orphaned memory that was
allocated by the derived type
destructors are called beginning with the most
derived class, then the parent class, then
grandparent, etc. up the hierarchy
6
inheritance: destructors
example
7
class MyBase {
public:
~MyBase() {
cout << "in ~MyBase\n";
}
void setData(int theData) { data=theData; }
protected:
int data;
};

class MyChild : public MyBase {
public:
~MyChild() {
cout << "in ~MyChild\n";
}
};
int main() {
MyBase base1;
MyChild mc;

MyBase* mbPtr=new MyChild;
MyChild* mcPtr=new MyChild;

cout << "deleting mbPtr\n";
delete mbPtr;

cout << "\ndeleting mcPtr\n";
delete mcPtr;

cout << "\nending main\n";
}
$ a.out
deleting mbPtr
in ~MyBase

deleting mcPtr
in ~MyChild
in ~MyBase

ending main
in ~MyChild
in ~MyBase
in ~MyBase

inheritance: destructors
example
8
class MyBase {
public:
virtual ~MyBase() {
cout << "in ~MyBase\n";
}
void setData(int theData) { data=theData; }
protected:
int data;
};

class MyChild : public MyBase {
public:
~MyChild() {
cout << "in ~MyChild\n";
}
};
int main() {
MyBase base1;
MyChild mc;

MyBase* mbPtr=new MyChild;
MyChild* mcPtr=new MyChild;

cout << "deleting mbPtr\n";
delete mbPtr;

cout << "\ndeleting mcPtr\n";
delete mcPtr;

cout << "\nending main\n";
}
$ a.out
deleting mbPtr
in ~MyChild
in ~MyBase

deleting mcPtr
in ~MyChild
in ~MyBase

ending main
in ~MyChild
in ~MyBase
in ~MyBase

memory view of inheritance
9
Employee HourlyEmployee
slicing!
10
class Parent {
public:
virtual int doSomething() {
cout << "in Parent, returning x\n";
return x;
}

private:
int x;
};

class Child : public Parent {
public:
int doSomething() {
cout << "in Child, returning y\n";
return y;
}

private:
int y;
};
void someImportantFunction(Parent p) {
//...some stuff
int important=p.doSomething();
//...
}
int main() {
Child c;
//...
someImportantFunction(c);
}
$ a.out
in Parent, returning x

remember: a pointer to a base type can point
to its own type or a derived class (aka
subclass, child class)
cant hold or point to objects up the hierarchy
(base/parent classes dont have all the pieces of
the derived)
a subclass has all members of the base class
(though they wont be directly accessible if the
base class members are private)
for functions, compiler searches up hierarchy
until finds it, if virtual inserts code to lookup at
runtime
11
multiple inheritance
is allowed in C++
if both have a speak() methodcompiler error if code tries to
call myCatDogInstance.speak()
can call myCatDogInstance.Dog::speak () (or
myCatDogInstance.Cat::speak()
can overwrite by defining CatDog::speak() { cout << meow-woof; }
or upcast: static_cast<Dog>(myCatDogInstance).speak();
12
Cat Dog
CatDog
adapted from Solter, Klepper Professional C++ . Wiley 2005.
multiple inheritance
13
Cat Dog
CatDog
adapted from Solter, Klepper Professional C++ . Wiley 2005.
Animal
abstract classes
Perhaps a pure virtual method virtual void speak() =
0;
Then cant create instances of Animal, to create
instances of subclass, must implement void speak()
Cat::speak() { cout << meow; }
Dog::speak() { cout << woof; }

15
Cat Dog
Animal
adapted from Solter, Klepper Professional C++ . Wiley 2005.
why abstract classes?
base classes that categorize concrete types:
Animal
no such thing as generic animal--dog, cat are
subclasses (concrete types that are animals)

interfaces
(the most common use of multiple inheritance)
(contrast with Java)
e.g. Clickable abstract class might only have an
onClick pure virtual function
any class that derives from Clickable (e.g.
Button or Folder) must implement the onClick
method
16
more on templates

17
std::string revisited
C++ string class is a template class
typedef basic_string<char> string;

http://www.cplusplus.com/reference/string/string/
18
template function example
19
template<typename T>
void shell_sort(std::vector<T>& v) {
const std::size_t n=v.size();
for (int gap=n/2; 0<gap; gap/=2) {
for (int i=gap; i<n; ++i) {
for (int j=i-gap; 0<=j; j-=gap)
{
if (v[j+gap]<v[j]) {
std::swap(v[j], v[j+gap]);
}
else break;
}
}
}
}

//(of course, you should just use
//std::sort
//#include <algorithm>)
int main() {
std::vector<int> intvec;
intvec.push_back(7);
intvec.push_back(2);
intvec.push_back(3);
intvec.push_back(6);
intvec.push_back(11);
intvec.push_back(9);

shell_sort<int>(intvec);
typedef std::vector<int>::iterator it
for (it i=intvec.begin();
i!=intvec.end(); ++i)
{
std::cout << *i << "\t";
}
std::cout << "\n";
}


$ a.out
2 3 6 7 9 11

stl algorithms
http://www.cplusplus.com/reference/algorithm/
for_each, find, count, copy, swap, fill,
random_shuffle, min_element, max_element,
many others
sort
takes [begin, end) random-access ([ ]) iterators




by default, compares elements using operator<
you can pass it a function or function object to use
instead
20
#include <algorithm>
using namespace std;
//
sort (myvector.begin(), myvector.end()); //(12 26 32 33 45 53 71 80)
sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33
how does compiler ensure just one copy of
each template instance?
with GNU ld (linker) on ELF or MS Windows:
compiler generates template instances in each
translation unit, then linker collapses them
together
disadvantage: increased compilation time because
template code may be compiled repeatedly
21
template class inheritance
You can use inheritance with template classes
template base class with template derived class
template base class with non-template derived
class
non-template base class with template derived
class
warning!
std::string and all stl containers DO NOT have virtual
destuctors -- DO NOT create derived classes!
someone asked me if you can create a subclass of
std::vectortechnically, yes, but dont do it!
vector * x = new Derived;
delete x;//calls ~vector, not ~Derived
and why would you want to?
22
template class inheritance
example
23
template<typename _denseVectorT,
typename _matrixT,
typename _propensitiesFunctorT,
typename _dependencyGraphT>
class TauLeapExpAdaptive : public SSA_Direct<_denseVectorT,
_matrixT,
_propensitiesFunctorT,
_dependencyGraphT>
{
typedef SSA_Direct<_denseVectorT,
_matrixT,
_propensitiesFunctorT,
_dependencyGraphT> Base;
//class declaration like you would expect...
std::size_t
in a lot of C++ code, youll see size_t
size_t (size type) is the type returned by sizeof operator
similar to unsigned int
recall what an unsigned int is?
size_t is guaranteed to be able to represent largest size your
system can hold
good practice to use size_t for sizes (in some cases, failure to do so
can lead to portability issueson many, but not all, systems, size_t has
the same range as unsigned int and unsigned long)
memcpy example see:
http://www.eetimes.com/discussion/programming-pointers/4026076/Why-size-t-
matters
24
material for final ends here!
25
function pointers
functions have an address in memory
we can create a pointer to a function
26
//typedef FunctionReturnType(*NameOfFuncPtrType)(function params)
typedef bool(*YesNoFunc)(int, int);

bool int_equal(int x, int y) {
return (x==y);
}

bool both_odd(int a, int b) {
return (a % 2 == 1 && b % 2 == 1);
}

void findMatches(int ary1[], int ary2[], int arySize, YesNoFunc compare) {
for (int i=0; i!=arySize; ++i) {
if (compare(ary1[i],ary2[i])) {
cout << "match item " << i << ", value= "<<ary1[i]<<"\n";
}
}
}
adapted from Solter, Klepper Professional C++ Wiley 2005.
27
int anArray[]={1, 3, 5, 7};
int anotherArray[]={7, 6, 5, 3};

cout << "using int_equal: \n";
findMatches(anArray, anotherArray, 4, int_equal);
cout << "\n";
cout << "using both_odd: \n";
findMatches(anArray, anotherArray, 4, both_odd);

$ a.out
using int_equal:
match item 2, value= 5

using both_odd:
match item 0, value= 1
match item 2, value= 5
match item 3, value= 7

function objects (aka functors)
objects that can be called like a function
sometimes called functions with state
overloaded operator()
30
class MyFunctor {//GreaterThan
public:
//...
bool operator()(int x, int y) {
return (x>y);
}
};
function objects (aka functors)
31
vector<int> myvec;
myvec.push_back(3);
myvec.push_back(6);
myvec.push_back(4);
myvec.push_back(1);

sort(myvec.begin(), myvec.end());
printvector(myvec);

MyFunctor myFtor;
if (myFtor(3,6)) {
cout << "3 is larger than 6\n";
}
else cout << "3 is NOT larger than 6\n";

sort(myvec.begin(), myvec.end(), myFtor);
printvector(myvec);

$ a.out
1 3 4 6
3 is NOT larger than 6
6 4 3 1

other notes about templates
if you dont provide the template arguments (e.g.
min(arg1, arg2) instead of min<SomeType>(arg1, arg2))
when you declare an instance of template class or call a
template function, the compiler will try to deduce the
type based on the arguments:




good practice to explicitly state the template arguments
32
template<typename T>
T min(T a, T b) { return a<b ? a:b; }
//...
int x=4, y=3;
int z=min(x,y);//T is deduced to be int
int z=min<int>(x,y);
template specialization
consider our Array template class from
previous class




works for any type
we can change the behavior of Array for a
particular type using template specialization

33
template <typename T>
class Array {
T* data;//dynamically allocated array of type T objects
int size;
T getValue(int index);//could use operator[]
//...
};
template specialization
suppose we want Array<bool> to manipulate an
array of bits instead of bool types
(to save memorya bool typically takes 1 byte=8 bits )
we declare a template specialization using the
syntax:

34
template <typename T>
class Array {
T* data;//dynamically allocated array of type T objects
int size;
T getValue(int index);//could use operator[]
//...
};
template <>
class Array<bool> {
//...declarations specific to Array<bool> type
//can provide different implementations, even different
//functions...
};
template partial specialization
you can provide partial specialization of
template classes that specializes one feature
but not others
probably most commonly used for pointer
types
the interface for pointers is different because you
(usually) want to operate on whats being pointed
to, not the pointer itself
e.g. this wont work for a pointer template argument:

it would be nice if we could do the following for all
pointer types:

35
if (x < y) { //...
if (*x < *y) { //...
template partial specialization
e.g. this wont work for a pointer template argument:

it would be nice if we could do the following for all
pointer types:

to declare a partial specialization for all pointer
types:

36
if (x < y) { //...
if (*x < *y) { //...
template <typename T>
class MyTemplateClass<T*> {
//same stuff as before (or different, if you choose)
//but with pointer dereference on all type T objects
//...
if (*x < *y) { //...
//...
func doSomething(T *val) {//...
};
template template parameters
say you want to make a stack template class
and you want it to be a container adaptor
has a template parameter for the underlying container
(like the stl stack)
e.g. make a stack, be able to use a vector OR a list as
the underlying data structure (btw stl stack uses deque
as default)
37
http://www.informit.com/articles/article.aspx?p=376878
template<typename T, typename Container>
class Stack { //... };

Stack<int, vector<int> > myStack1;
Stack<int, vector<double> > myStack2;//allowed but bad!
template template parameters
above is basically how stl stack is
implemented (but with deque instead of vector)
could provide additional safety with template
template parameters:
38
http://www.informit.com/articles/article.aspx?p=376878
template<typename T, typename Container = vector<T> >
class Stack { //... };

Stack<int> myStack1;//Container is vector<int>
Stack<int, vector<double> > myStack2;//see, still dangerous
template <typename T, template <typename> class Container>
class Stack {
//...
private:
Cont<T> data;
};
inheritance: copy ctor,
operator=
we know the copy constructor and assignment
operator are important if declaring dynamic
memory in a class
in a subclass, you usually want to be sure to
call the parent copy constructor instead of the
parent default constructor within the function
similarly, you usually want to call the parent
assignment operator within a derived class
operator=
40
inheritance: copy ctor,
operator=
41
class Base {
public:
Base();
Base(const Base&);
Base& operator=(const Base&);
};

class Sub : public Base {
public:
Sub();
Sub(const Sub&);
Sub& operator=(const Base&);
};

Sub::Sub(const Sub& other) : Base(other)
{ // ...
}

Sub& Sub::operator=(const Sub& other) {
if (&other==this) return *this;
Base::operator=(other);//Call Base's assignment op
//...do Sub-specific assignments
}
homework 4 due Thurs. (8/19) at beginning of
class (hard copy)
extra credit homework 5 posted; due Friday
8/27 (day after final) 11:59pm (using turnin
commandfollow instructions)
contact instructor with questions
homework 5 will not be accepted after 11:59pm
on 8/27 (--no 24-hour 25%-penalty grace period)

additional office hour? Friday morning?
11:00?
44
course overview and remaining schedule
architecture basics, OS basics, linux, shell scripts, compilation, libraries
C++, classes and objects, constructors, destructors, operator
overloading, static members, dynamic memory, program layout in
memory, namespaces, casts, testing and exceptions, hash tables
inheritance and polymorphism, abstract classes, template
classes/functions (generics), standard template library: containers,
iterators, algorithms
45
week date topic
9 8/17 class (today) more inheritance/templates
8/18 lab continue lab 8: Page Rank project
8/19 class review homework 4
fun stuff not on final exam
(suggestions?)?
10 8/24 class final review
8/25 lab extra credit lab
8/26 class final exam
course evals
Course: CS 32
Instructor: Kevin Sanft
46