Announcements
CSCI 334: Principles of Programming Languages HW8 pro tip: the HW7 solutions have a complete, correct implementation of the CPS version of bubble sort in SML. All you need to do is encode the same Lecture 19: C++ logic in C++.
Instructor: Dan Barowy
Dynamic Dispatch (ala Smalltalk) Announcements Superclass Point object Point class Template
x 2 y
3 Method dictionary Code newX:Y: I’ve decided to skip Java. ColoredPoint object ColoredPoint class … move 2 3 purple Method dictionary Code
Template newX:Y: x color y foo color Call move on ColoredPoint Optimize Dynamic Dispatch Superclass Superclass Point object Point class Template Point object PointPoint vtableclass Template
x x 2 4 y 2 y
3 Method dictionary Code 3 Method dictionary Code
ColoredPoint object ColoredPoint class newX:Y: newX:Y: 5 … … move move 1 2 2 6 • Static types let us do some optimization. 3 • Sacrificing runtime polymorphism-by-default also allows optimization. purple Method dictionary Code • Statically determine locations of x and y. Template newX:Y: x • Non-virtual method lookup determined statically. 3 color y • Copy virtual methods from superclasses into method dictionary. foo color • Eliminate class object; just a “virtual function table” now.
Optimize Dynamic Dispatch Call move on ColoredPoint C++ virtual dispatch never searches as in SmallTalk!
Point object Point vtable Code Point object Point vtable Code
… … 2 x move 2 x move 3 3 y 3 y
ColoredPoint object ColoredPoint vtable Code ColoredPoint object ColoredPoint vtable Code
… … 2 x move 2 x move 1 2 3 y color 3 y color purple color foo purple color foo Runtime polymorphism Runtime polymorphism • You may have forgotten how OO polymorphism works. • You may have forgotten how OO polymorphism works. • It’s easy to forget with Smalltalk, which is dynamically typed. • It’s easy to forget with Smalltalk, which is dynamically typed. • In Java—and especially C++—you need to think about this or it • In Java—and especially C++—you need to think about this or it will bite you. will bite you. class Animal { class Human : public Animal { class Animal { class Human : public Animal { public: public: public: public: string myName() { string myName() { virtual string myName() { virtual string myName() { return "Animal"; return "Human"; return "Animal"; return "Human"; } } } } }; }; }; }; Animal *a = new Animal(); Animal *a = new Animal(); cout << a->myName() << endl; cout << a->myName() << endl;
Human *h = new Human(); Human *h = new Human(); cout << h->myName() << endl; cout << h->myName() << endl;
a = h; a = h; cout << a->myName() << endl; cout << a->myName() << endl; • What will the last line print? • What will the last line print?
Inheritance vs Subtyping Initializer Lists
class Pirate : public Person { public: Pirate(string name); Pirate::Pirate(name) : Person(name) {} virtual void sayHello(); } • In C++, the base class constructor is called automatically for you for no-argument constructors. • Recall that inheritance and subtyping are not the same. • When calling a superclass constructor with an argument from a • Example: implement a stack using a dequeue. subclass, you must use initializer list syntax. This is different from • Inheritance of the form: Java. class
String::~String() { delete []s; }
Automatic vs. Heap Allocation Type Inference!
• C++ has a restricted form of type inference. allocated on the stack!
int main() { int main() { Pirate dan = Pirate(“Dan”); auto dan = Pirate(“Dan”); dan.sayHello(); access member using “.” dan.sayHello(); Pirate *karen = new Pirate(“Karen”); auto karen = new Pirate(“Karen”); karen->sayHello(); karen->sayHello(); } allocated on the heap }
access member using “->” (remember, this is syntactic • auto makes life wonderful. Use it unless you are confused sugar) about inferred types (in which case, write the type manually) Lambda expressions Lambda expressions
• C++ has lambda expressions. 3 1 2 • They are a tad more verbose than in SML. [ ]( ){ } • Three main components. Let’s rewrite this SML lambda expression in C++: [ 3 ]( 1 ){ 2 } fn (x: int) => x + 1
1. Parameter list 2. Function body [](int x ){ return x + 1; }; 3.Capture list
Lambda expressions Lambda expressions
[ 3 ]( 1 ){ 2 } [ 3 ]( 1 ){ 2 }
Let’s rewrite this SML lambda expression in C++: Let’s rewrite this SML lambda expression in C++: val y = 2 val y = 2 fn (x: int) => x + y fn (x: int) => x + y
int y = 2; int y = 2; [ y ](int x ){ return x + y ;}; [ &y ](int x ){ return x + y; };
Captures y “by value” (copies value of y) Captures y “by reference” (refers to y) Lambda expressions Lambda subtleties
What is the type of a lambda expression?
[&y](int x){return x + y;}; Capture of closed-over lambda parameters is only This one takes an int and returns and int necessary for variables with “automatic storage std::function
More generally.. (demo) std::function
Templates Templates
• C++ lets you program “generically” just like Java or SML. • No restriction on template parameter like Java (int vs Integer)
• Syntax is a little different. • Works by generating specialized code (literally, a new class) at • Mechanism is very different. compile-time for each parameter type used.
template
• You can even template lambda expressions. • Unfortunately, the typedef mechanism does not understand • Here’s a generic identity function. template parameters, which means that you have to fix the template parameter if you use it. template
Next class
• Scala wrap-up
• Logic programming