Sie sind auf Seite 1von 16

Lec1

-c++ is middle level language because both procedural (low level) and OO (high l
evel)
-compiles to machine code
-class is described by declaration, in ClassName.h, and definition, in ClassName
.cpp
-declaration: declares name for class, class's members (functions protot
ypes and data members) and their visibility -> ENDS IN SEMICOLON
#ifndef CLASS_NAME_H
#define CLASS_NAME_H
class ClassName {
public: ClassName();
protected:
private:
}; // <---------------#endif
-definition: contains implementation of function prototypes
#include "ClassName.h"
ClassName() {
}
-pointer have two pieces of info, memory address and type (or void) of o
bject pointed to
-& translates item to reference,
i.e. b gets address of variable a: int a =5, int * b=&a;
-* dereferences pointer to access item stored at location of memory
-Note: Circle * myCircle=new Circle(5);
//*myCircle.area(); is wrong, (*myCircle.area()); is wrong, (*my
Circle).area() is right, but the best is
myCircle->area();
-c++ files compiled one at a time (unlike java), so classes must be declared bef
ore used
-thus, class declarations can be seperated from implementation in .h fil
e and then included using compiler directive:
#include "className.h"
-treats .h file as if were in source code where #include stateme
nt is
-we seperate files because in large projects, many files use same class
-includes can accumulate (if you include a file that includes other files you ge
t them all), so only include files you need
-Include guard: used to ensure we don'y unintentionally include more than one de
claration per class
i.e.
#ifndef CLASS_NAME_H
#define CLASS_NAME_H
class ClassName {
};
#endif
-The class declaration (inside Class { };), gives scope for labels (variables an
d function names)
-once outside of class we need to specify we want to use it (i.e. in cpp
) by going ClassName::FunctionName() {}
i.e. Circle::Circle(double radius) {
this->radius = radius;
}
-We can create arbitrary scope using namesapaces, and access variables of namesp
ace by either double colons or by declaring that you are "using" specific namesp
ace

-used to reduce naming conflicts


-standard libraries in std name space, i.e. std::cout
-(note only for nonprimitive time, i.e. not int, bool, long, float, char
i.e. namespace myExample {
int someVar;
int anotherVar;
} //dont do this in this course
can do myExample::somevar = 1;
i.e.
#include
using std::cout; // can also use entire name space instead with
// using namespace std; //NOTICE that neither using comes with # sign before it
int main() {
cout<< "a word" <<std::endl;
}
Lec2.1 function calls
-reference type holds address of variable or object, but behaves syntactically l
ike a variable
int a=45; int& c=a; c=10;// do not need dereference and now a = 10;
-reference types when defined, refers directly to what it references and cannot
be left null nor uninitialized
-also can not be reassigned to reference other variables at diff locatio
ns of memory
-pointers refer directly to 32 bit memory address, can be left null and unitiali
zied, and can be reassigned to reference other variables at different locations
of memory
-function has syntax
returnType name (paramaters) { statements; }
-function allocates new frame on call stack allocating space for local v
ariables which gets removed when function exits and call frame popped
-can pass parameter to function and return a value from function by value, point
er, or reference
-pass by value: value of param copied into call frame of function
Function def:
}{nvoid
um =addTen(
num + 10int num )
Function call:
addTen(x); //value of x unchanged
-pass by pointer: value of actual paramater copied into call frame of fu
nction (but value copied is memory address)
Function def:
}{*void
p_numaddTen(
= (*p_num)
int* +p_num
10 )
Function call:
int x;
addTen(&x); // value of x changes
-pass by reference: written like pass by value in function definition an
d when calling function (except for & in formal paramter) and behaves like pass
by pointer
Function def:
}{nvoid
um =addTen(
num + 10int& num )
Function call:
int x;
addTen(x);
//value of x changes
-Returning by value returns value of specified time, returning by pointer return
s pointer to value of specified to type, by reference returns reference
i.e. Return by reference
Func def:

{}int&
reieturn
f ( xmax(int
lse
> y ) &x, int &y)
x;
y;
Func Call: int a=3, b=5;
cout << max(a,b) << endl;
-NOTE
MyClass * obj1=new MyClass(); // pointer on stack to object on heap
MyClass obj2(): // Object on call stack
MyClass * ob3=&obj2; pointer to object on call stack
-can point from stack to heap, or stack to stack in earlier frames i.e. passing
by reference
-no pointer should point to object in later call frame (possible
when returning pointers), or from heap to stack
-thus, object can be local variables when object is only used within function, p
ointers to object passed to other functions as parameters, and no pointer to obj
ect is returns or given to heap objects
-variable should be on heap when pointing from object to other object on
heap, or when we want to pass back object as return value

2.2
-standard c++ library introduces string class in string library
-#include <string>
-intializing strings (if using namespace std; or using std::string;
string str1("Hello World");
string sr2= "Hi There!";
string str3(5,'*'); <- 5 asterisks in a row
-to copy string: string str; string str2("SUP");
str.assign("hi"); // str now stores hi
str.assign(str2); //str stores sup
-concatenating strings: string str1; string str2("man");
str1.append(str2); // str1="man"
str1.append(80,'*'); // str1=man*** //77 more *
-accessing individual characters
str.at(index);
-computing string length:
str.length();
-c++ allows operators to be overloaded, string library makes heavy use of operat
or overloading
i.e. oneString.assign(another) <-> oneString=another;
oneString.append(another) <-> onestring+=another;
oneString.at(n);
<-> oneString[n];
also if(str1 < str2) or >, >=, <=, ==
-i/o in c++ occurs in "streams"
-stream= sequence of bytes of indefinite length
-input: bytes flow from device into main memory
-output: bytes flow from main memory to a device
-<< : stream insertion operator, write data to stream
->> : stream extraction operator, write data from stream
-defined for all standard c++ data types, and can be overloaded
to work with our classes
-std::cin: standard input stream, std::cout : standard output stream, std::err :
standard error stream, std::clog: buffered error stream
--<< >> are left associative and so can be chained
-standard input and output is included in iostream library
-#include <iostream>
std::string name;
std::cout << "Type name: ";

std::cin >> name;


cout << "Your name is " << name << endl
-fstream library provides ifstream (interface to read data from files as input s
treams), ofstream (interface to write data to files as output stream)
-#include <fstream>
using std::ifstream;
main () {
ifstream in_file;
string str;
in_file.open("input.txt");
if(in_file.fail()){
cout<< "error" << endl;
}else{
infile >> str;
cout << "First word from file: " << str;
in_file.close();
}
}
-as you can see, with file streams formatted input works the same as cin
-C++ allows to work with various i/o devices using consistent interface
-file output
#include <fstream>
using std::ofstream;
main();
ofstream out_file;
int year=2012;
out_file.open("output.txt");
if (out_file.fail()) {
cout << "error" << endl;
}
else{
outfile << "The year is " << year << endl;
outfile.close();
}
}
-sstream library provides istringstream, to manipulate string as input stream; o
stringstream, to manipulate as output stream;
i.e. #include <sstream>
using std::istringstream;
main() {
string time("5h22m");
istringstream in_str(time);
char ch;
int hours, minutes;
int_str >> hours >> ch >> minutes ;
}
using std::ostringstream;
main() {
int hours=5, minutes = 22;
ostringstream out_str;
out_str << hours << "h" << minutes << "m" ;
string time = out_str.str();
}
-iomanip library provides i/o manipulators that act as filters upon input/output
-endl: new line and flush buffer
-setw(n): set min field width
-left : left justify fields
-right : right-justify field

-setfill(ch) used after setw to set fill character


-in binary operation, i.e. +, overloaded operator method is called on left hand
side of operator i.e.
Time t1; Time t2; t1+t2; //equivelant to t1.operator+(t2);
cout << "hi" ; //equivelant to cout.operator<<("hi");
-however, we do not have access to cout class to implement overloaded << operati
on for a user defined type
-so must use a global function that is not member of any class
in .h file:
friend ostream& operator<<(ostream& out, Rectangle& r);
friend istream& operator>>(istream& in, Rectangle& r);
in.cpp file:
Rectangle::Rectangle() {}
ostream& operator<<(ostream& out, Rectangle& r) //note, global so no namespace::
{
out << "[" << r._x << "," << r._y << "," << r._width << "," << r._height << "]
";
return out;
}
istream& operator>>(istream& in, Rectangle& r)
{
char c;
in >> c; // Read the [
in >> r._x;
in >> c; // Read the ,
in >> r._y;
in >> c; // Read the ,
in >> r._width;
in >> c; // Read the ,
in >> r._height;
in >> c; // Read the ]
return in;
}
-note that operator overloads in header file declared using keyword frie
nd
-when class declares friend function, allows access to private members w
ithin function
-better to use getters and setters though and drop the friend de
claration
-C++ has type safe I/O in that each i/o function defined to handle particular da
ta type, and if function called cannot handle data type we get compiler error ro
data cannot sneak through system like in c

Lecture 3 - managing object resources


-C++ has no memory management, so programmer must ensure dynamically allocated m
emory is reclaimed at end of program
-memory allocated when entering a scope (i.e. calling a function), space allocat
ed on call frame for local variables; when new is called, space allocated on hea
p for object,
-memory reclaimed when leaving a scope, stack space used by local scope reclaime
d, and when delete is called, heap space used by object reclaimed

-can't rely on compiler to initialize values (i.e. default value of any time cha
nges from machine to machine)
-constructor called when object of class created
-allows one to gaurantee member variables of new data type always initia
lized properly
-should initialize all members of class in constructor, i.e. primitive types get
meaningful value, objects call appropriate constructor, and pointers assigned a
t meaningful address with entity initialized at address
-default constructor: constructor with no arguments
-generated by compiler if no constructors are defined
-default constructs base class, default constructs any object me
mbers, performs no other initializations
-when executing constructor, before entering code of constructor, already create
s space for members and calls constructors for member objects
-thus will call default constructors, and if initailized inside construc
tor, then reinitialize any object values inside constructor
-solve problem by initializization list allowing us to specify which con
structors to use when creating object
syntax (in .cpp file) ClassName::ClassName(varOneType nameOne, varTwoType nameTw
o) : _varOneName(nameOne), _varTwoName(nameTwo) {
//rest of constructor
}
i.e. Person::Person(string name, string pet_name) : _name(name), _pet(pet_name)
{}
-destructor called when object destroyed and reclaims ddynamically allocated mem
ory and release resources (close files, database connections, etc.)
-called when variable holding object goes out of scope, or when delete c
alled on pointer to object
-cannot be overloaded
-syntax in .h file: ~ClassName(); in .cpp file: ClassName::~ClassName() {//conte
nts }
-when members of class destroyed, primitive type members' space reclaimed implic
itly following destructor, object type members' space reclaimed implicitly follo
wing destructor (each objects' destructor called implicitly), space for pointers
must be reclaimed because space reclaimed for pointer only
-if destructor not defined for class, compiler implicitly defines it as empty, w
hich still correctly reclaims memory for primitive and object members, but will
not delete pointer referenced data
-when new is called, space allocated on heap for data and constructor called
-when delete is called, destructor called and space reclaimed
-any data allocated with new, should be reclaimed with delete
-any data allocated with new[] should be reclaimed with delete[]
-delete[] only deletes space allocated for array and does not de
lete array elements
-general rule: if new called in constructor, should call delete
in destructor
-copy constructor called when creating an object by copy an EXISITNG object
i.e. Person p1("Jeff"); Person p2=p1; // copy constructor Person p3(p1); //copy
constructor
-called when passing object as parameter by value, or when returning by
value
i.e. void f(Person p) //calls copy constructor on Person P
{ return p; }// p copied again when returned by value
-syntax of copy constructor:
ClassName::ClassName(const ClassName& other) {..}
i.e. Person::Person(const &Person other) _name(other._name), _bff(other._bff) {}
-parameter must be reference and must be const (so we cannot change obje
ct)

-defualt copy constructor: generated by compiler if no copy constructor defined


-generates shallow copies: makes copies of data members in class, but sh
ares
-initializing an array done by int * values=new int[5]; or by int a[6];
-if object has pointers, we likely want implement deep copy semantics (makes cop
ies of pointers references also)
i.e.
976543812{IntArray
10
11
13
14
15
}this
{for ->
}this
(int
->_values
::i =IntArray
_values
0;=[i]
i=new
<new=this
(int
const
int
other
[this
->
[size
IntArray
other
_size
[i];
) :;._size
->
_size
size
++i)
& other
];()
( size
];) :)_size ( other . size ())
}
-19}delete
20
21
22
{IntArray
[] this
::~ IntArray
-> _values
() ;
-Assignment operator similar to copy construcot, but called when assigning objec
t to an object that has already been initialized to a value
-more responsibility: must test against self assignment, clean up existi
ng object, and return reference to *this
-compiler generates default assignment operator if none is providing implementin
g shallow copy semantics
i.e. in .h file
IntArray& operator=(const IntArray& other); ClassName& operator=(const ClassName
& other);
-in.cpp file
19 IntArray & IntArray :: operator =( const IntArray & other ) //always in copy
20
constructo
21
22
23
24
26
27
28
29
31
25 this
30
if
{int
}temp
for(*(int
delete
this
[i]
->
temp
[]_values
=ithis
!=other
= 0;
& ->
new
other
=i[i];
int
< this
_values
temp
[) ;other
->; _size
. size; ++i)
() ];
32 }return *this; //always in copy constructor!!!!
-best practices: define default constructor, explicitly define destructor, even
if empty
-rule of three: if you need one, you probably need all copy, assignment, and non
empty destructor
-i.e. if class manages pointers to dynamically allocated entities
Lecture 4
-STL=standard template library, library of generic algorithms and data structure
s
-provides data structures such as vector, list (doubly linked), set, map
-introduces iterators: usedd to iterate over range of elements in data structure
-makes use of C++ templates, allowing STL containers to be instantiated to conta
in any data type
-with c++ templates, template definitions and declaration must be visible in sam
e translation unit so all code goes in .h file
-class always begins with
template <class T> //T is variable representing class
-constructors and destructors contain type paramated in angle brackets
i.e. ClassName<T>() { } ~ClassName<T>
-everywhere else, type t can be used anywhere normal variable used
i.e. void add(T value) { }
-reduces duplication, provides flexibility and maintaibility
876931
10
11
12
13
14
15
17
18
19
20
22
23
24
25
27
28
29
30
32
33
34
16public
21
26
template
class
List
delete
{this
}return
T*
int
};
~List
Tvoid
private
get(
_elements
_nextIndex
List
<T
->
add
:<Tthis
[]
int
<class
>()
_nextIndex
_elements
:(T
>()
{index
this
value
->
; ;_elements
T>)[this
->
==new
)_elements
0; ->
T[[ index
MAX_CAPACITY
_nextIndex
;
]; ++]];= value ;
//in main.cpp
926
10
11
12
13
15
16
18
19
21
22
24
25
27
28
14main
17
20
23
{ ()<<
List
string
strList
intList
}cout
<<int
string
s2
s1intList
.add
strList
=> "intList
(s1);
(s2);
(4)
(3)
> .strList
hello
world
;get";
; (1)
(0); << endl ;
-STL vector provides array that is dynamically resized
-#include <vector>; using std::vector; vector<int> numbers;
-vector.push_back(3); cout<< numbers[0];
-STL pair allows two values of different types to be coupled
-#include <utility>
pair<string,double> product1("manor",1);
pair<string, int> pr2("heaven", 7);

cout << pr2.first << "=" << pr2.second << endl;


-STL map provides associative array mapping keys to values
-#include <map> using std::map;
map<string,int> grades; grades["assfuck"]=3;
map<int, string> Employees;
11
12
// 1) Assignment using array index notation
13
Employees[5234] = "Mike C.";
14
Employees[3374] = "Charlie M.";
15
Employees[1923] = "David D.";
16
Employees[7582] = "John A.";
17
Employees[5328] = "Peter Q.";
18
19
cout << "Employees[3374]=" << Employees[3374] << endl << endl;
20
21
cout << "Map size: " << Employees.size() << endl;
22
23
for( map<int,string>::iterator ii=Employees.begin(); ii!=Employees.end(); ++i
i)
24
{
25
cout << (*ii).first << ": " << (*ii).second << endl;
26
}
-STL algorithms can be applied to arrays and iterators #include <algorithm>
-reverse can reverse elements from index until one position before speci
fied element
-int a[5]={1,2,3,4,5}; reverse(a, a+5);
-find can find an element in an array from index until specified pointer
-int val=find(a,a+5,end);
transform takes a method and array, and index and apply to all elements
in array up to index
-transform(a,a+5,method_name);
-iterator provides generalization of a pointer
-points to specific element in data structure, can increment/decrement i
terators to iterate over elements of data structure
-each STL aglorithm excepts iterators as parameter
-pointers are really itereators which is why we can use STL algo
rithms on array
-Each stl data structure contains four methods providing types of iterators
-begin() -return iterator pointing to first element
-end() - one position past last element in data structure
-rbegin() - reverse iterator pointing to last element in data structure
-rend() - reverse iterator pointing one before first element in data str

ucture
-can do iterator arithmetic just like pointer arithmetic
i.e. reverse(v.begin()+1,v.end()-1);
-iterator supports dereference and pointer operator to access value curr
ently pointed at by operator
-obviously used for iterating
i.e. std::vector<string> v;
v.push_back("hello"); v.push_back("world");
for(std::vector<string>::iterator it = v.begin(); it!=v.end(); ++it) {
cout << (*it) << endl;
cout << it->length() >> endl;
}
Lecture 5- const correctness
-const: keyword specifying that data should not be modified
-both pointers and data can be const, so use right to left rule
-note * goes to right of pointers and left of type
int* const * b // pointer to a constant pointer to an integer
const int* const * const d // constant pointer to constant pointer to constant i
nteger
-cannot assign constant data to a pointer to non constant data, also cannot cons
tant pointer to nonconstant pointer
i.e. const char * h = " Hello ";
char* w=World;
h[1]='u'; does not compile because const data
h=w; // compiles because non constant pointer
char* const h="Hello";
char* w="World";
h[1]='u'; //compiles because nonconst data
h=w; // does not compile because pointer is constant
-we can assign address of non-const object to const pointer, (we promise not to
change something that is ok to change)
i.e. i=4;
const int* j=&i; //this is fine!
-we cannot assign address of const object to nonconst pointer though
const int i=4;
int* j=&i; //compilation error
-string literals like "hello" are technically a const char* but we can assign it
to a char* (this is an exception to the general rule)
-in function declaration const can refer to return value, paramater, or function
as whole
-const data returned by value can be assigned to non const variable beca
use we are simply copying return values into variable, not taking variable itsel
f
-so for built in types, pointless to declare them as const becau
se cannot be used as lvalue anayways i.e. sum(3,4)=5 //error
-good idea for user defined types to be returned by value becaus
e assignments like the one below are legal if return value is not const
i.e.const
const
Rational
(a
}{...
return
* b)Rational
a=+a,c;
Rational
b;b,//c;
&assign
rhs);
operator
to the*(product
const Rational
of a * bconst
& lhs int
, sum(int a, int b)
int i= sum(3,4);
-data returned by pointer or reference should almost always be returns a
s const data
ie. Person
string
& name
( string
() { return
name )_name
: _name
; }( name ) { }

allows for
Person
p.
namep("
() =Jeff
"Joe";
");
-so this is much better: const string& name() { return _name ; }
-first choice for paramater should be const reference because efficient (no copy
ing), syntax is identical to passing by value, and passing const means we cannot
change referenced object
-also allows us to accept temporaries,i.e. "hello", because temporaries
always const
}{ie.void
cout << name
printName
<< endl
( string
;
& name )
printName ("Joe"); // compilation error !
-so this is much better: void printName ( const string & name );
-we methods are created in a class, compiler inserts a 'constant pointer to this
' as first parameter in methods signature so
{class
};
const string
Person & name ();
compiles to
{class
};
const string
Person & name ( Person * const this );
-when we call method on object, compiler silently passes pointer to object as f
irst parameter
i.e. Person p;
p.name(); -> compiles to name(&p);
-if we declare method to be const, that causes this to be const
-thus, specifies that we cannot make changes to state of reciever in met
hod (i.e. this->name="manor; would generate error in const method)
i.e. const string & name () const ; compiles to -> const string& name(const Pers
on* const this);
-also means that we cannot call non-const methods within method on "this
" regardless of whether methods actually change reciever
-if method is declared const, then reference and pointer types returned must be
declared const
-two definitions of const:
-bitwise constness: does not modify bits of object
-conceptual constness: can modify object, but only in ways undetectable
to clients
-c++ implements bitwise constness
-methods differing only in their constness can be overloaded
-can use mutable keyword for bitwise constness, by declaring data member
s mutable -> they can be changed in const methods
i.e. mutable int _length;
-by overloading[] operator, const and nonconst strings handled differently
-if pointer of reference param is not modified - should be declared const, if po
inter of reference member returned - should be const, if function does not chang
e member data should be const
Lecture 6
-benefits of inheritance: reusability, extensibility (add functionality), polymo
rphism (write generic code handling multiple types)
-syntax
class Person{}
class Student : public Person {} // DONT FORGET PUBLIC
-if Person has constructors:
{Person
}Person (()const string & name ) : _name ( name )
and Student has
{:Student
} Person(name),
( const _number
string &(name
number
, const
)
string & number )
-default constructor in person called when instantiating new student
-so must call specific superclass constructor in initialization list
{:Student
} _number( (const
numbephotor
string &)name , const string & number )
-if there is no default constructor in superclass, and forget to call sp
ecific constructor in initialization list of subclass, you get an error

omething
-if data
-if data
-if data

of our
member
member
member

-if access
ss
-if access
protected
-if access
ase class

-note we cannot call constructors of our own type to construct s


type, can only call constructors of base class
is public: accessible to subclasses and clients
is protected: accessible to subclasses, inaccessible to clients
is private: inaccesible to subclasses, and clients

specifier is public, all data members remain as they are in super cla
specifier is protected, then all data members in baseclass are either
or private
specified is private, all data members in base class are private in b

-Polymorphism: allows use of derived classes through base class pointers/referen


ces
i.e. Student s; Person * p = &s;
-method called depends on pointer type through which method was invoked
-p->sayHello() person s->sayHello() student
-called static dispatch and computed at compile time
-virtual keyword enables dynamic dispatch
-with dynamic dispatch: method called depends on type of data pointed to
by pointer
-computed at runtime such that subtypes might override method
-tradeoff between efficency because runtime lookup in vtable, so only de
clare overridable methods virtual
-NOTE: VIRTUAL only specified in header file: not implemenation file
-method declared virtual stays virtual in all subclasses but convention
is to continue adding virtual as reminder
{i.e.
virtual
};
pclass
ublicclass
Student
:voidPerson
sayHello
: public();
Person
-pure virtual function: no implementation, known as abstract method and used to
force subclasses to implement particular method
-abstract class: having one or more pure virtual functions
-cannot be instantiated, subclass is concrete/'not abstract' iff all inh
erited pure virtual functions implemented
-destructors always declared virtual
-note superclass desctructor and subclass destructor called when methods
declared virtually
-compiler-generated copy constructor will call copy constructor of base class
-custom copy constructor must specify in initialization list that we want to cal
l default copy constructor of Person, such that default person constructor wont
be called in student copy constructor
i.e.
Student
_number
39
40
41
{
}cout
)( const
<<
"In Student
Studentcopy
& other
constructor
) : Person
" <<( endl
other;), _number ( other .
-same thing with assignment operator, compiler generated operator calls assignme
nt operator of base class, so custom assignment operator should do the same make
sure to call the superclass assignment operator i.e.
53
54
55
56
58
59
60
61
62
64
57 }this
63
Student
{cout
Person
if ( ->
return
<<
this
::
*_number
&this
"In
operator
!=Student
&;other
= other
=(assignment
)other
const
. _number
Student
);
operator
; & other
" <<)endl ;
-can't have virtual constructors
-if assigning subclass to superclass variable, additional members in subclass ar
e sliced off in the assignment, leading to strange results if you try and then a
ccess the sliced off members
Lecture 7
-conversions can be implicit i.e. float f=3.14; double d=f; or Student s; Person
p=s;, or explicitly (casts)
-C++ supports c-style casting i.e. int n=5; float f=(float)n/3.2;
-C++ has 4 new cast operators: const_cast, static_cast, dynamic_cast, and reinte
rpret_cast
-const cast used to strip away constness of a variable

-syntax: const_char<type>(varName);
i.e. const char* str="Hello World";
printstring(str); //doesn't work because parameter is non const
printstring(const_cast<char*>(str));
-static_cast is similar to c-style but safer
-syntax: static_cast<type>(varName);
i.e. float f= static_cast<float>(i);
-allows down casting, but not upcasting
-dynamic cast used to safely convert pointer/references up and down inheritance
hierarchy
-only works with polymorphic types (at least one method in source type v
irtual)
-works by checking run-time infoo stored in vtable of object
-object only has vtable if has virtual method, so only works on
classes with at least one virtual method
-i.e. Class Person{}; class Student : public Person {}; class Employee:
public Person(){};
41 Student
42
Person **p1s1==new
dynamic_cast
Person (" <JoeStudent
"); *>( p1); // s1 == NULL because Person s
tored in pointer
Student
53
54
55 Person
Student
* *s2*p2=s3=new
=s2;
dynamic_cast
Student (" Joe
< Student
", " 250000000
*>( p2);");
// //s3==s2 because dynamic ob
ject checks object stored by pointer and finds student
66 Student
65
Employee**s4e1==dynamic_cast
new Employee<("Student
Joe ",*>(
1234)
e1);; // e1 is null because object s
tored by pointer is employee
-reinterpret_cast reinterprets bits of object
i.e. float* f= new float(3.25);
int* i=reinterpet_cast<int*>(f); //address of i is same as f
-reinterpret cast is dangerous, could easily lead to crashes
-can be used to emulate generics however using void*
-when compiler encounters c style cast attempts following casts
const cast, static_cast, static_cast followed by const_cast, reinterpret_cast, r
einterpret_cast followed by const_cast
-first option satisfying requirements of cast operator is selected (so m
ay employ reinterpret cast)
-c++ casts easier to find by searching
-c++ allows classes to define conversion operators specifying how objcet should
be implicitly converted to given type
i.e. in class if you want your class to to be able to made into a type done like
operator typeToConvertInto() const {
return a; // a is of TypeToConvertInto type;
} allowing
ClassName a;
typeToConvertInto s=a;
in cpp file you say
operator string() const {
ostringstream ss;
ss << _cell << " = " << _value;
return ss.str();
}
so if type of object is Cell, then can do
Cell("a1",3.14);
string s=cell;
-no return type specified because return type is specified by name of operator,
and always const because original object unchanged

Lecture 8 - User Stories


-Big design up front: traditional requirements analysis
-talk to stakeholders, develop UML model, get all requirements up front,
then code
-problems: difficult envisions all requirements up front, documenting ev
ery requirements tedious and error prone, people change their minds, requirement
s documents extremely long, wasted time making requirements that cannot be imple
mented in time
-software is intangible: very hard to estimate all tasks that mu
st be completed, their order, and their duration
-requirement changes are called a "change of scope'
-people who need software must communicate requirements to developers
-project relies on information from business perspective and development
perspective
-if business side dominates, then requirements are made for func
tionality and deadlines without concern whether they are deliverable on schedule
, and the team udnerstands whats requested
-if development side dominates,replaces language of business/dom
ain with technical jargon
-thus, since requirements often change, reliable estimation difficult, coming up
with all requirements up front difficult - we spread decision making across dur
ation of project
-user story: describes functionality valuable to customer
-3 components: card, written description of story used for planning; con
versation, conversations about story to flesh out details; confirmation, test th
at confirm when story is complete and convey document details
-stories written by customer team: ensures software will meet needs of users
-includes developers, testers, users, customers
-stories must be written in language of business - not technical jargon such tha
t customers can priotitize stories
-user story is "reminder to have conversation", i.e. discuss details with custom
er at time when this is important (just-in-time requirements analysis)
-Cards represent customer requirements, details worked out in conversation and r
ecorded in confirmation
-front of card: user story, estimate in story points
-A recruiter can post a new job (3 points)
-cost of story: estimate given to story by developers
-cost in story points indicating size and complexity of story relative t
o other stories (i.e. 4 points takes twice as long as 2)
-each team defines meaning of story points (i.e. one ideal day of work)
-back of card contains "acceptance tests" that verify story was developed to wor
k exactly how customer team intended
-run frequently, usually automated
-goal is to convey additional info so developers know when story is done
-Example: Story: A user can pay for items in her shopping cart with a credit car
d
Test with different
Visa
aDiner
good
expired
Visa,'sbad
MasterCard
debit
cards
Club
purchase
, and
card
( fail
missing
(and
amounts
pass
)).American
).(tryExpress
security
going
codesover
( pass
card).limit )
-by providing tests early, customer team states expectations and reminds develop
ers of situations they may forget
-iteration length: customer team and developers must choose length of each itera
tion (usualy 1-4 weeks), and iteration length rematins constant
-at end of each iteration, developers responsible for delivering fully u
sable code for some subset of application
-velocity; developers estimate how much work (in story points) they can complete
each iteration
-sort stories into piles representing iterations, where stories in each
pile add up to no more than estimated velocity
-highest priority goes into first iteration, next second, etc.

-as we complete iterations, we learn development teams actual velocity and work
with it instead of estimated velocity
-thus, we may need to sort piles again for new velocity
-for planning releases, customer must prioritize stories based on; desirability
of feature to broad or important base of users, and cohesiveness of story in rel
ation to others
-customer team ultimately sets priorities in manner maximizing value delivered t
o organization
-traditional waterful model (big design up fron): write requirements, analyze th
em, design solution, code, test
-customers involed at only beginning and end
-story-driven project: customers and users involved throughout duration of proje
ct
-Good stories follow INVEST acronym: Independant, Negotiable, Valuable, Estimabl
e, Small, Testable
-independant: dependancies between stoies should be avoided because leads to pri
oritizsation and planning problems
-thus, should combine dependant stories into larger independant stories
and find different way to split story
-negotiable: stories are not contracts or reminders, but should be negotiable
-stories are only reminders to have conversation, so need to negotiate d
etails in conversation between customer team and development team (known details
are written on card however)
-i.e. shouldn't have too little detail so developers understand the requ
irement, but definitely shouldn't have too much either
-Valuable: user stories should be valuable to users and customers
-i.e. should be written so that benefits of story to customer/users are
apparent
-allows customers to prioritize stories
-Estimable: three reasons why a story might not be estimable: too big, developer
s lack domain knowledge, developers lack technical knowledge
-if developers lack domain knowledge, should discuss with customer who w
rote story
-if developers lack technical knowledge, send one or more developers on
spike: brief experiment to learn about area of application learning just enough
to estimate the task
-if story is too large, developers need to break it into smaller stories
-large stories called epics, which are useful as placeholders re
minding about big parts of system necessary to discuss
-Small: stories should be small, but not too small (i.e. A user should be able t
o add a resume)
-Testable: story that sucessfully passing its tests must proves story has been s
uccessfully developed
-untestable stories with nonfunctional requirements are bad (i.e. A user
must find software easy to use)
-User stories: emphasize conversations with users/cutomer team, comprehensible t
o customers and developers, right size, work for iterative development, encourag
e just in time developement
Lecture 9 - Design Principles
Design Principle 1: Encapsulate what varies: take part that vary and encapsulate
them, so later can alter or extend parts that vary without affecting those that
don't
-I.E. If you have a bunch of classes, i.e. TypeOfDuck, inheriting from D
uck and whether some behaviour exists in that class varies according to the subc
lass, sometimes duck fly, and sometimes ducks quack
-rather than putting methods that vary into superclass, we creat
e interface/abstract class for each behaviour that varies i.e. FlyBehaviour, Qua
ckBehaviour, and we create classes that implement those interfaces for the vario
us behaviours of the subtype, i.e. FlyWithWings, FlyUnable, Quack, Squeek, Mute

that override methods fly() and quack()


-Now store interface type pointers as part of superclass, i.e. D
uck now store memebr FlyBehaviour* _flyBehaviour; and QuackBehaviour data member
which holds an object of type FlyWithWings, FlyUnable, etc.
-now each subclass will store an approrpriate behaviour
for what varies
-benefits: eliminates code duplication, behaviours can be reused, objects can dy
namically change behaviours at runtime
-Design Principle 2: Code to an interface, not an implementation
-interface we're talking about is an abstract class or concrete supertyp
e, so we mean: code to a supertype, not a subtype when possible
-i.e. suppose we want to model teams of athletes and we have athletes of
different subtypes
one option: create Team and subclass for each specific team type
-but creates large inheritance hierarchy, and results in
extensive code duplication
-better option: create Team class with addPlayer that takes a po
inter of Athlete interface type
Design Principle 3: favour delegation, composition, and aggregation over inherit
ance
-inheritance establishes IS-A relationship
-composition/aggregation establishes a has-a relationship
-i.e. with duck example, ducks get behaviour by being composed with the right be
haviour object
-benefits: creating systems using composition gives increased flexibilit
y, encapsulates algorithms in own class, can change behaviour at run-time
-rule of thumb: if you need to use functionality in another class, but d
on't need to change functionality, consider using delegation instead of inherita
nce
-i.e. in Document class has vector of DocumentFilters used to Fi
lter document
-an object composed of owns the objects owns that object (black diamond at big s
ide)
-when object is destroyed, so are all object it is composed of
-when considering composition or aggregation, ask whether you need to track obje
ct outside of larger class
-if not, use composition (owns a)
-if so, use aggregation (has a)
-aggregation: an object composed of other objects,but the objects exist outside
of the object as well
-when object is destroyed, objects composing it remain
-white diamond at big side
-SOLID - Single repsonsibility principle, open/closed principle, liskov substitu
tion principle, interface segregation principle, dependancy inversion principle
-Design principle 4: single responsibility principle: every object in system sho
uld have single responsibility, and all objects services focused on carrying out
responsibility
-responsibility = reason for object to change
-when a class has mroe than one reason to change, likely trying to do to
much
-break up class into multiple classes where each individual has
a single responsibility and only one reason to change
-benefits: results in high cohesion (extent to which elements of a modu
le belong together)
-Design Principle 5: Open/Closed principle: classes should be open for extension
, and closed for modificatio
-source code should be closed for modification, and any behavioural chan
ges should be accomplished by subclassing or other means, shouldn't touch tested
code
-allows behaviour of code to be modified without touching code

-Design Principle 6: liskov substitution principle: subtypes must be substitutab


le for their mase types
-when inheriting from base class, must be able to substitute subclass fo
r base class without affecting program correctness
-LSP states that any method on a superclass should be usable on a subcla
ss (and also yield meaningful results)
-IS A, does not tell whole story of whether inheritance is correct
-Use inheritance when objects behave like each other, rather the
n just IS A relationship
Design Principle 7: Interface segregation principle: many client-specific interf
aces are better than one general purpose interface
-fat interface: class whose interface not cohesive (too many responsibil
ities)
-if classes are seperate, interfaces should be seperate
-so don't add new methods appropriate to only one or a few implementatio
n classes
-divide bloated interface into smaller more cohesive interfaces,
and new classes can implement only ones that are necessary
-i.e make classes inherit/implement multiple subclasses
-Design Principle 8: Dependency Inversion principle: high level modules should n
ot depend on low-level modules< both should depend upon abstractions
-causing system to become rigid: difficult to change, and fragile: easil
y broken
-i.e. make higher level class independant of lower level classesit contr
ols so it can be reused freely
-called dependancy inversion
-i.e. rather than making high level class simply use classes of
different types, make superclass for classes of different types and store pointe
r to superclass variable in class, that could point to classes of different type
s
-thus method used depends on object stored in pointer ra
ther than what method you call, so classes are independant
-Design Principle 9: principle of least knowledge: talk only to your immediate f
riends
-ideally for any method in an object, we should only invoke methods that
belong to object itself, object passed in as parametr to method, object that me
thod creates or instantiates, any components of object (i.e. data member)
-Design Principle 10: Dry principle (don't repeat yourself)
-mostly means don't duplicate code

Das könnte Ihnen auch gefallen