Programowanie obiektowe

Transkrypt

Programowanie obiektowe
Programowanie obiektowe
dr inż. Marcin Pietroo
History of programming languages
Języki programowania
TIOBE LIST:
1. C
2. C++
3. Objective-C
4. Java
5. C#
6. Visual Basic
7. PHP
8. Python
9. JavaScript
10.Visual Basic .NET
11. Ruby
12. Transact-SQL
13. Perl
14. F#
15. Język asemblera
16. Lisp
17. PL/SQL
18. MATLAB
19. Delphi
20. Object Pascal
Programming languages
Programming languages
• set of syntax rules
• semantic
Choosing language for implementation:
• efficiency
• available libraries
• experience
• domain of implementation
Programming languages
• Newer languages with higher abstraction
• old languages were low level languages strictly
based on CPU architecture
• portability and abstraction shorten time of
software development, error risk (very often
worse efficiency)
Elements of programming lanaguages
•
•
•
•
syntax
semantic
data types
standard libraries
Programming languages – syntax and
semantic
• Lexems (token) definitions
• Syntax rules
Syntax defined by regular expressions and BNF
notation
Gramar definition
BNF notation is a production rules set:
• <symbol> ::= <expression with symbols>
Semantic of used symbols is as follows:
• < – left boundary of symbol
• > – right boundary of symbol
• ::= – is defined as
• | – or
Above symbols are meta language symbols.
BNF – liczba naturalna
• <zero>::= 0
• <non zero numbers>::= 1 | 2 | 3 | 4 | 5 | 6 | 7
|8|9
• <digit>::= <zero> | <non zero number>
• <digits> ::= <digit> | <digit><digits>
• <positive integer number>::= <digit> | <non
zero digit><digits>
BNF – C language
conditional_expression
: logical_or_expression ('?'^ expression ':'
conditional_expression)? ;
logical_or_expression
: a=logical_and_expression ('||'^ b=logical_and_expression)*;
logical_and_expression
: inclusive_or_expression ('&&'^ inclusive_or_expression)* ;
inclusive_or_expression
: exclusive_or_expression ('|'^ exclusive_or_expression)* ;
BNF – C language
compound_statement
: '{' declaration* statement_list? '}';
statement_list
: statement+ -> ^(STMT statement+);
FLOATING_POINT_LITERAL
: ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix?
| '.' ('0'..'9')+ Exponent? FloatTypeSuffix?
| ('0'..'9')+ Exponent FloatTypeSuffix?
| ('0'..'9')+ Exponent? FloatTypeSuffix
;
Programming languages – data types
• integers
• floating points (float, double)
• text data (char)
Standard libraries
•
•
•
•
•
input/output functions
files system handling
multithreading
operating memory handling
basic data types and procedures to processing
them
• text data structures
Types of errors
•
•
•
•
•
•
lexical error
syntax error
casting error
semantic error
execution error
logic error
Errors
•
•
•
•
foor (int i = 0; i < 100; i++) - lexical
x+1 = x - syntax
for (int i = 0, i < 100, i++) - syntax
main() {i = 0;} - semantic
Programming languages processing
• compilation – source code is translated to
machine code. Compiled programming
languages
• interpretation – source code is translated
online and executed by special program called
interpreter. Interpretated programming
languages
Classification of programming
languages
• programming paradigms (imperative, functional,
declarative)
• type of generating machine code
• control of data types compatibility (e.g. dynamic
typed)
• type of execution (compiled, interpretated)
• level of abstraction (low or high level)
• purpose (database modification, markup
languages, bash languages, hardware languages
etc.)
Compilation - lexer
• The process of converting a sequence of
characters (such as a computer program or
web page) into a sequence of tokens
• A program that performs lexical analysis may
called lexer, tokenizer, or scanner ("scanner"
is also used to refer to the first stage of a
lexer).
Compilation - lexer
• lexer is generally combined with a parser,
which together analyze
the syntax of programming languages, web
pages.
• Regular expressions (identify tokens)
• finite automata (finite state machine) with
state table
Lexer
• sum = i + 8;
Lexem
Token category
sum
"Identifier"
=
"Assignment"
i
„identifier"
+
"Addition"
8
"Integer literal"
;
"End of statement"
Compilation - parser
• Parsing or syntactic analysis is the process of
analysing a string of symbols, either in natural
language or in computer languages,
conforming to the rules of a formal grammar.
• Parser get lexer output as an input
• Generate Abstract Syntax Tree (AST)
Parser
• Top-down parsing - top-down parsing can be viewed as
an attempt to find left-most derivations of an inputstream by searching for parse trees using a top-down
expansion of the given formal grammar rules. Tokens
are consumed from left to right.
• Bottom-up parsing - a parser can start with the input
and attempt to rewrite it to the start symbol.
Intuitively, the parser attempts to locate the most basic
elements, then the elements containing these, and so
on. LR parsers are examples of bottom-up parsers.
Another term used for this type of parser is ShiftReduce parsing.
Proces kompilacji
• lexer –> tokens –> syntactic analysis –>
• parse tree (AST, intermadiate representation)
–> compiler, interpreter, translator ->
• other language, virtual machine ->
• machine code etc.
Abstract Syntax Tree
FUNC_DEF
FUNC_BODY
DECL
DECL
COMPOUND_STMT
EXPR
Time_START
Time_END
COMPOUND_STMT
EXPR
EXPR
EXPR
EXPR
i
=
6
EXPR
EXPR
Compilation – tools for lexer and
parser generating
•
•
•
•
•
Yacc
ANTLR
SUIF
Flex
Ragel
C language
•
•
•
•
variables
basic data types (int, float, double, char etc.)
arrays (static and dynamic)
structures
C language
• pointers (int*, double* etc.)
• references (int & etc.)
C language
• functions (parameters by value and addresses,
local variables, list of parameters etc.)
• conditional instructions (if etc.)
• loops (for, while etc.)
C language
Memory allocation:
- malloc, realloc …
- free
Struktury danych
•
•
•
•
•
preprocesor
define (literal values, macros)
include
ifdef
…
Data structures
•
•
•
•
•
List
Vektor
Hashmap
Stack
Set
Data structures
• Binary trees
• Red black trees
• Heap
List implementation
• How list can be implemented in C?
List
struct element
{
int value;
struct element *next;
};
struct element* head = malloc(sizeof(struct
element));
head->value = 1;
head->next = NULL;
Lista
struct element* addLastElement(struct element* tail, int val) {
struct element* new_tail = malloc(sizeof(struct element));
new_tail->value = val;
new_tail->next = NULL;
tail->next = new_tail;
return new_tail;
}
struct element* addFirstElement(struct element* head, int val) {
struct element* new_head = malloc(sizeof(struct element));
new_head->value = val;
new_head->next = head;
return new_head;
}
Lista
struct element* removeFirstElement(struct element* head) {
struct element* new_head = head->next;
free(head);
return new_head;
}
void print_list(struct element * head) {
struct element * current = head;
while (current != NULL) {
printf("%d\n", current->value);
current = current->next;
}
}
Lista
struct element* removeElement(struct element* head, int nr) {
struct element * current = head;
struct element * previous = head;
int count = 0;
while (current != NULL) {
count++;
if (count == nr) {
current = current->next;
previous->next = current;
}
previous = current;
}
}
Task
• Bidirectional list
Data structures
• Graph
Task – tree implementation
Data structures
• Tree traverse
• Methods of tree traverse?
Tree traverse
PRE-ORDER(node_v) {
print node_v.value
jeżeli node_v.left_child != null to PRE-ORDER(node_v.left_child)
jeżeli node_v.right_child != null to PRE-ORDER(node_v.right_child)
}
IN-ORDER(node_v) {
jeżeli node_v.left_child != null to IN-ORDER(node_v.left_child)
wypisz node_v.value
jeżeli node_v.right_child != null to IN-ORDER(node_v.right_child)
}
POST-ORDER(node_v) {
jeżeli node_v.left_child != null to POST-ORDER(node_v.left_child)
jeżeli node_v.right_child != null to POST-ORDER(node_v.right_child)
wypisz node_v.value
}
Basic algorithms
- Sorting
- Text algorithms
- Tree and graph algorithms
Algorithms - sorting
•
•
•
•
•
•
Insertion
Bubble
Quick sort
Merge sort
Counting sort
Heap sort
Algorithms
• Time complexity
• Memory complexity
Text algorithms
•
•
•
•
KMP
Naive
Boyer Moore
Aho-Corasick
Text algorithms
• Regular expressions
• Network intrusion
• Databases
Object oriented programming
• Object languages:
- Java (business applications, mobile software
etc.)
- C++ (embedded, real-time, financesector)
- Python (prototyping, testing)
- Smalltalk
- Ruby (web)
- Objective-C (mobile)
-…
Object oriented programming
• programming paradigm - data structures
called "objects", contain data, in the form
of fields, often known as attributes; and code,
in the form of procedures, often known
as methods.
Object oriented programming
• a feature of objects is that an object's
procedures can access and often modify the
data fields of the object with which they are
associated,
• in OO programming, objects in a software
system interact with one another.
Object oriented programming
• There is significant diversity in object-oriented
programming, but most popular languages
are class-based, meaning that objects
are instances of classes, which typically also
determines their type.
Object oriented programming
Languages that support object-oriented programming
use inheritance for code reuse and extensibility in the
form of either classes or prototypes. Those that use
classes support two main concepts:
• Objects - structures that contain both data and
procedures
• Classes - definitions for the data format and
available procedures for a given type or class of
object; may also contain data and procedures (class
methods)
Object oriented programming
• Objects sometimes correspond to things found in
the real world (e.g. a graphics program may have
objects such as „figure ", "circle ", "square" or "
cursor ", online shop may have objects such as
"shopping cart" "customer" " basket " or "product
",
• Objects can represent more abstract things and
entities, like an object that represents an open
file, or an object which provides some service
(e.g. xml parsing)
Object oriented programming
Object is an instance of a particular class. Procedures in objectoriented programming are known as methods, variables are also
known as fields, members, attributes or properties.
• Class variables - belong to the class as a whole; there is only one
copy of each one
• Instance variables or attributes - data that belongs to
individual objects; every object has its own copy of each one
• Member variables - refers to both the class and instance variables
that are defined by a particular class
• Class methods - belong to the class as a whole and have access only
to class variables and inputs from the procedure call
• Instance methods - belong to individual objects, and have access to
instance variables for the specific object they are called on, inputs,
and class variables
Class definition
class TComplex
{
private:
double fRe;
double fIm;
// the real part
// the imaginary part
public:
// Getters / Setters
double GetRe( void ) const { return fRe; }
double GetIm( void ) const { return fIm; }
void SetRe( double re ) { fRe = re; }
void SetIm( double im ) { fIm = im; }
};
Class definition
public class Complex {
private double fRe;
private double fIm;
public void setRe(double re) {fRe = re;}
public void setIm(double im) {fIm = im;}
public double getRe() {return fRe;}
public double getIm() {return fIm;}
}
Definicja klasy
public class Complex {
private double fRe;
private double fIm;
public void setRe(double re) {fRe = re;}
public void setIm(double im) {fIm = im;}
public double getRe() {return fRe;}
public double getIm() {return fIm;}
public static void length(Complex c) {
…
}
}
Object oriented programming
• „Pure" OO languages, because everything in them is treated consistently
as an object, from primitives such as characters and punctuation, all the
way up to whole classes, prototypes, blocks, modules, etc.
Examples: Eiffel, Obix, Ruby, Scala, Smalltalk, Self.
• Languages designed mainly for OO programming, but with some
procedural elements. Examples: Delphi/Object
Pascal, C++, Java, C#, VB.NET.
• Languages that are historically procedural languages, but have been
extended with some OO features. Examples: Pascal, Visual Basic (derived
from BASIC), Perl, COBOL 2002, PHP, Ada 95.
• Languages with abstract data type support but without all features of
object-orientation. This includes object-based and prototypebased languages. Examples: Modula-2, JavaScript, Lua.
• Chameleon languages that support multiple paradigms, including OO,
hybrid object system that supports both prototype-based programming
and class-based OO (Tcl).
Object oriented programming
•
•
•
•
•
Dynamic dispatch/message passing
Inheritance
Polymorphism
Abstraction
Encapsulation
Dynamic dispatch/message passing
• by definition, it is the responsibility of the
object, to 'on-demand' select the procedural
code to run/execute in response to a method
call, by looking up the method at run time in a
table associated with the object,
• multiple dispatch - if there are multiple
methods that might be run for a given name
(this process require some language support).
Objects and methods invocation
int main() {
TComplex a, b, c;
TComplex d( 10, 20 );
std::cout << c.GetRe() << std::endl;
std::cout << d.GetRe() << std::endl;
}
Constructors - arrays
#include <iostream>
using namespace std;
class Box {
public:
Box() {
cout << "Constructor called!" <<endl;
}
~Box() {
cout << "Destructor called!" <<endl;
}
};
int main( ) {
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // Delete array
return 0;
}
Constructors - arrays
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Objects and methods invocation
public static void main(String[] args) {
Complex a = new Complex();
Complex c = new Complex(10, 20);
System.out.println(c.fRe);
}
Composition
• Objects can contain other objects in their
instance variables,
• For example, an object in the Employee class
might contain (point to) an object of the Address
class, in addition to its other own instance
variables,
• Object composition is used to represent "has-a"
relationships: every employee has an address, so
every Employee object has a place to store an
Address object.
Composition
class Address {
private:
std::string street;
std::string city;
int houseNumber;
…
};
class Employee {
private:
std::string name;
Address address;
…
};
Composition
public class Address {
private String street;
private String city;
private int houseNumber;
}
public class Employee {
private String name;
private Address address;
}
Inheritance
• Languages that support classes almost always support inheritance.
• This allows classes to be arranged in a hierarchy that represents "isa-type-of" relationships.
• For example, class Employee might inherit from class Person. All the
data and methods available to the parent class also appear in the
child class with the same names.
• For example, class Person might define variables "first_name" and
"last_name" with method "make_full_name()". These will also be
available in class Employee, and with additional variables "position"
and "salary".
• This technique allows easy re-use of the same procedures and data
definitions, with similar real-world relationships,
Inheritance
public class Person {
protected String first_name;
protected String last_name;
public String make_full_name() {
return first_name+last_name;
}
}
public class Employee extends Person {
private String position;
private int salary;
}
Inheritance
class Person {
protected:
std::string first_name;
std::string last_name;
public:
std::string make_full_name() {
return first_name+last_name;
}
};
class Employee: public Person {
private:
std::string position;
int salary;
};
Inheritance
• Subclasses can override the methods defined by
superclasses.
• Multiple inheritance is allowed in some languages (this can
make resolving overrides complicated),
• Some languages have special support for mixins, though in
any language with multiple inheritance, a mixin is simply a
class that does not represent an is-a-type-of relationship.
Mixins are typically used to add the same methods to
multiple classes. For example, class
UnicodeConversionMixin might provide a method
unicode_to_ascii() when included in class FileReader and
class WebPageScraper, which don't share a common
parent.
Overriding
public class Employee extends Person {
protected String position;
protected int salary;
public String make_full_name() {
return last_name;
}
}
Overriding
class Employee: public Person {
protected:
std::string position;
int salary;
public:
std::string make_full_name() {
return last_name;
}
};
Overloading
public class Employee extends Person {
private String position;
private int salary;
public String make_full_name(int parameter) {
return last_name;
}
}
Inheritance
• Abstract classes cannot be instantiated into
objects, they exist only for the purpose of
inheritance into other classes which can be
instantiated (not abstract). In Java, the final
keyword can be used to prevent a class from
being subclassed.
• The "open/closed principle" - classes and
functions "should be open for extension, but
closed for modification".
Abstract classes
public abstract class Figure {
protected int position;
protected String name;
public void draw() {
}
public String getName() {
return name;
}
}
Abstract Class
class Figure {
protected:
std::string name;
int position;
public:
virtual void draw() {
}
virtual std::string getName() {
}
};
Inheritance vs Composition
• The doctrine of composition over inheritance
advocates implementing is-a-type-of
relationships using composition instead of
inheritance.
• For example, instead of inheriting from class
Person, class Employee could give each
Employee object an internal. Some languages,
do not support inheritance at all.
Encapsulation
• If a class disallows calling code from accessing internal
object data and forces access through methods only, this is
a strong form of abstraction or information hiding known as
encapsulation.
• Some languages (Java, C++ for example) let classes enforce
access restrictions explicitly, for example denoting internal
data with the private keyword and designating methods
intended for use by code outside the class with
the public keyword.
• Methods may also be designed public, private,
intermediate levels such as protected (which typically
allows access from other objects of the same class, but not
objects of a different class) or default.
Encapsulation
• This facilitates code refactoring, for example
allowing the author of the class to change how
objects of that class represent their data
internally without changing any external code,
• Encourages programmers to put all the code that
is concerned with a certain set of data in the
same class, which organizes it for easy
comprehension by other programmers.
• Encapsulation is often used as a technique for
encouraging decoupling.
Polymorphism
• Subtyping, a form of polymorphism, is when calling code
can be agnostic as to whether an object belongs to a parent
class or one of its descendants. For example, a function
might call "make_full_name()" on an object, which will
work whether the object is of class Person or class
Employee. This is another type of abstraction which
simplifies code external to the class hierarchy.
• In languages that support open recursion, object methods
can call other methods on the same object (including
themselves), typically using a special variable or keyword
called this or self. It allows a method defined in one class to
invoke another method that is defined later, in some
subclass
Polymorphism (java example)
Person p = new Employee("Nowak", "Jerzy");
System.out.println(p.make_full_name());
Polymorphism (C++)
• Static linkage (binding)
• Dynamic linkage (binding)
Polymorphism (C++)
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
virtual int area() = 0;
Polymorphism (C++)
class Figure {
protected:
int width, height;
public:
Figure( int a=0, int b=0) {
width = a;
height = b;
}
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Figure {
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area () { cout << "Rectangle class area :" <<endl; return (width * height); }
};
Polymorphism (C++)
Figure *shape;
Rectangle rec(10,7);
shape = &rec;
shape->area();
Object life cycle
• creation (constructors)
• state changes of object
• removal (destructor)
Keyword const
int a = 0;
const int b = 1;
a = 10; // b=11; Error!
class example {
public:
void funkcja_1(void) const;
void funkcja_2();
...
};
int main() {
example a;
const example b;
a.funkcja_1();
b.funkcja_1();
a.funkcja_2();
// b.funkcja_2(); Error!
}
Initialization - constructors
•
•
•
•
default
parameterized
copying (C++)
if defined constructor by programmer no
defult constructor (must be redefined)
• no return values
Constructors
• defined constructors can be public (most
popular, public classes), protected, private
(hardly ever e.g. in Singleton pattern, private
classes)
Constructor (not parametrized)
Complex( void ) : fRe( 0.0 ), fIm( 0.0 )
{
}
Constructor (with parameters)
Complex( double re, double im ) : fRe( re ), fIm( im )
{}
Complex( double re, double im ) {
fRe = re;
fIm = im;
}
Complex( double re) : fRe( re ) {}
Copy constructor
Complex( const Complex & c ) : fRe( c.fRe ), fIm(
c.fIm ) {}
Utilization: function parameters, initialization of
object by other object
Copy constructor
Complex c(10.0, 1.0);
Complex d = c;
Sequence of constructor execution
•
base object-> derivative
Example:
class Figure {
private:
int x;
int y;
std::string name;
public:
Figure() { cout << "figure default" << endl; }
Figure(int _x, int _y) : x(_x), y(_y) { cout << "figure" << endl; }
void rysuj() {}
};
Constructors
class Square: public Figure {
private:
int color;
int width;
public:
Square(int _x, int _y, int c) : Figure(_x, _y), color(c) {
cout << "square" << endl;}
Square(int c) : color(c) { cout << "square" << endl;}
};
int main() {
Square s1(1, 2, 10);
Square s2(10);
}
Objects removing
• Destructors (C++)
~Complex() {}
• Garbage collector (Java)
Destructor invocation
• By operator delete (dynamic objects)
• At the end of block (static objects)
Sequence of destructor execution
~Figure() {
cout << "figure deallocate" << endl;
}
~Square() {
cout << "square deallocate" << endl;
}
int main() {
Square * s = new Square(1,2,10);
delete s;
}
Destructors
~Complex() {
std::cout << "destroyed" << std::endl;
}
main() {
…
Complex* complex = new Complex(10.0, 1.0);
Complex c(10.0, 1.0);
…
delete complex;
}
Object oriented programming
class TComplex
{
private:
double fRe;
double fIm;
// the real part
// the imaginary part
public:
///////////////////////////////////////////////////////////
// The class constructors
///////////////////////////////////////////////////////////
TComplex( void ) : fRe( 0.0 ), fIm( 0.0 )
{
}
TComplex( double re, double im ) : fRe( re ), fIm( im ) {}
TComplex( const TComplex & c ) : fRe( c.fRe ), fIm( c.fIm ) {} // copy constructor
// Getters / Setters
double GetRe( void ) const { return fRe; }
double GetIm( void ) const { return fIm; }
void SetRe( double re ) { fRe = re; }
void SetIm( double im ) { fIm = im; }
~TComplex() {}
};
Operator this
void SetRe( double re ) {
this->fRe = re;
}
void SetIm( double im ) {
this->fIm = im;
}
C++ inheritance
public – dziedziczenie pól publicznych jako
publiczne, prywatnych jako prywatne,
chronionych jak chronione
C++ inheritance
protected - dziedziczenie pól publicznych jako
chronione, prywatnych jako prywatne,
chronionych jak chronione
C++ inheritance
private - dziedziczenie pól publicznych jako
prywatnych, prywatnych jako prywatne,
chronionych jak prywatne
Multi inheritance
example:
class Drawable {
void rysuj() {}
};
class Figure {
private:
int x;
int y;
std::string name;
public:
Figure() { cout << "figure default" << endl; }
Figure(int _x, int _y) : x(_x), y(_y) { cout << "figure" << endl; }
void rysuj() {}
};
Multi inheritance
class Square: public Figure , Drawable{
private:
int color;
int width;
public:
Square(int _x, int _y, int c) : Figure(_x, _y), color(c) { cout << "square"
<< endl;}
};
int main() {
Square s;
s.rysuj(); //błąd
}
Java – Multi inheritance
interface Drawable {
}
public class Figure {
}
public class Square extends Figure implements
Drawable {
}
Overloading operators
Complex & operator = ( const Complex & c )
{
if( this != & c )
// check for a conditions
such as: a = a
{
fRe = c.fRe;
// if not the same, then
fIm = c.fIm;
// copy element by element
}
return * this;
}
Overloading operators
Complex c(10.0, 1.0);
Complex d;
d = c;
cout << d.GetRe() << ", " << d.GetIm() << endl;
Overloading operators
Complex & operator = ( const Complex & c )
{
if( this != & c ) // check for a conditions such as:
a=a
{
fRe = c.fRe; // if not the same, then
fIm = c.fIm; // copy element by element
}
return * this;
}
Overloading operators
bool operator == ( const TComplex & c ) const
{
return fRe == c.fRe && fIm == c.fIm;
}
TComplex operator + ( const TComplex & second_op ) const
{
TComplex retComplex( fRe + second_op.fRe, fIm +
second_op.fIm );
return retComplex;
}
Overloading operators
std::istream & operator >> ( std::istream & i, TComplex & complex)
{
double re, im;
i >> re;
i >> im;
complex.SetRe( re );
complex.SetIm( im );
return i;
}
std::ostream & operator << ( std::ostream & o, TComplex & complex)
{
o << complex.GetRe() << ", " << complex.GetIm();
return o;
}
Template (szablon)
C++ functionality for creating code independent from data types
and algorithms.
• function templates
• class templates
Template
template <class T> class List { ... };
List <int> list;
List <std::string> list;
List <Element> list;
Template (szablon)
#include <iostream>
#include <string>
using namespace std;
template <typename T> T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main () {
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
return 0;
}
Template
template <class T> class Stack {
private:
vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
};
template <class T> void Stack<T>::push (T const& elem) {
elems.push_back(elem);
}
template <class T> void Stack<T>::pop () {
elems.pop_back(); }
Template
int main() {
Stack<int> intStack; // stack of ints
Stack<string> stringStack; // stack of strings
intStack.push(7);
stringStack.push("hello");
}
Java - generic
• Generic methods
• Generic classes
Generic method
public class GenericMethodTest {
public static < E > void printArray( E[] inputArray ) {
for ( E element : inputArray ) {
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] ) {
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "Array integerArray contains:" );
printArray( intArray );
System.out.println( "\nArray doubleArray contains:" );
printArray( doubleArray );
System.out.println( "\nArray characterArray contains:" );
printArray( charArray );
}
}
Generic class
public class Box<T> {
private T t;
public void add(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}}
Friend method
• Nie jest ważne w którym miejscu klasy (private, protected, public)
zostanie przyjaźo zadeklarowana. Przyjaźnie danej klasy są
stosunkowo ważne z punktu widzenia projektanta, stąd też
deklaracje przyjaźni zaleca się deklarowad na samym początku
deklaracji klasy.
• Przyjaźo nie jest dziedziczona.
• Gdy istnieje wiele przeciążonych funkcji, funkcją
zaprzyjaźnioną klasy jest tylko ta funkcja, która ma zgodną listę
argumentów z zadeklarowaną funkcją zaprzyjaźnioną.
• Funkcja może byd przyjacielem wielu klas.
• Funkcją zaprzyjaźnioną może byd zarówno funkcja globalna, jak i
funkcja składowa innej klasy.
• Funkcja zaprzyjaźniona nie jest składnikiem klasy, która deklaruje
przyjaźo.
Friend class and method
class A {
friend void function( A& ); // deklaracja przyjaźni
friend void B::function( A& ); // deklaracja
przyjaźni funkcji składowej klasy B
int attr;
};
void fun( A& obiekt ) {
obiekt.attr = 1;
cout << obiekt.attr;
}
Exceptions
1) An exception is a problem that arises during the
execution of a program
2) Response to an exceptional circumstance
3) Keywords:
• throw - program throws an exception
• try - try block identifies a block of code for which
particular exceptions will be activated
• catch - program catches an exception with an
exception handler at the place in a program
where you want to handle the problem
Exceptions
try {
// protected code
}
catch( ExceptionName e1 ) {
// catch block
}
catch( ExceptionName e2 ) {
// catch block
}
catch( ExceptionName eN ) {
// catch block
}
Exception - example
double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}
Exceptions - example
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}
catch (const char* msg) {
cerr << msg << endl;
}
Exceptions - example
struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
int main() {
try {
throw MyException();
}
catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
catch(std::exception& e) {
//Other errors
}
}
Exceptions - example
class MyException : public exception
{
public:
const char * what ()
{
return "C++ Exception";
}
};
Exceptions - example
try
{
throw MyException();
}
catch(std::exception& e)
{
std::cout << "exception" << std::endl;
}
catch(MyException& e)
{
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
Exception
Description
std::exception
An exception and parent class of
all the standard C++ exceptions.
std::bad_alloc
This can be thrown by new.
std::bad_cast
This can be thrown
by dynamic_cast.
std::bad_exception
This is useful device to handle
unexpected exceptions in a C++
program
std::bad_typeid
This can be thrown by typeid.
std::logic_error
An exception that theoretically
can be detected by reading the
code.
std::domain_error
This is an exception thrown when
a mathematically invalid domain is
used
std::invalid_argument
This is thrown due to invalid
arguments.
std::length_error
This is thrown when a too big
std::string is created
Exception
Description
std::out_of_range
This can be thrown by the at method from
for example a std::vector and
std::bitset<>::operator[]().
std::runtime_error
An exception that theoretically can not be
detected by reading the code.
std::overflow_error
This is thrown if a mathematical overflow
occurs.
std::range_error
This is occured when you try to store a
value which is out of range.
std::underflow_error
This is thrown if a mathematical
underflow occurs.
Static
void func(void);
static int count = 10;
main() {
while(count--) {
func();
}
return 0;
}
// Function definition
void func( void ) {
static int i = 5; // local static variable
i++;
std::cout << "i is " << i ;
std::cout << " and count is " << count << std::endl;
}
Namespace
namespace namespace_name {
//code declarations
}
name::code;
Input/output
• iostream
• fstream
ifstream
ofstream
void open(const char *filename, ios::openmode mode);
fstream afile; afile.open("file.dat", ios::out | ios::in );
// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n ); // position n bytes forward in fileObject
fileObject.seekg( n, ios::cur ); // position n bytes back from end of
fileObject fileObject.seekg( n, ios::end ); // position at end of fileObject
fileObject.seekg( 0, ios::end );
Casting
•
•
•
•
const cast
static cast
dynamic cast
reinterpret cast
Const cast
Konwersja uzmienniająca ma postad
• const_cast<Typ>(wyrazenie)
• Wyrażenie wyrazenie musi tu byd tego samego
typu co Typ, tylko
z modyfikatorem const lub volatile.
• Konwersja usuwa „ustalonośd” (lub „ulotnośd”)
i może służyd tylko do tego celu.
• W innych przypadkach const Typ → Typ
nielegalne
Static cast
Konwersja statyczna ma postad
• static_cast<Typ>(wyrazenie)
dokonuje jawnego przekształcenia typu, sprawdzając, czy jest to przekształcenie dopuszczalne na
etapie kompilacji.
Często użycie tego operatora jest zbędne, bo konwersja i tak zostanie dokonana.
double x = 4;
int i = x;
warning: initialization to `int' from `double'
warning: argument to `int' from `double'
możemy uniknąd jawnie dokonując konwersji:
double x = 4;
int i = static_cast<int>(x);
Dynamic cast
Konwersja dynamiczna ma postad
• dynamic_cast<Typ>(wyrazenie)
• Konwersje dynamiczne stosuje się, gdy prawidłowośd
przekształcenia nie może byd sprawdzona na etapie
kompilacji (zależy od typu obiektu klasy
polimorficznej).
• Typ ten jest znany dopiero w czasie wykonania i wtedy
ma miejsce sprawdzenie poprawności.
• Konwersje używane są wyłącznie w odniesieniu do klas
polimorficznych i tylko dla typów wskaźnikowych
i odnośnikowych
Reinterpret cast
„Najsilniejszą” formą konwersji jest konwersja wymuszana. Ma ona
postad
• reinterpret_cast<Typ>(wyrazenie)
• Użycie takiej konwersji oznacza, że rezygnujemy ze sprawdzania jej
poprawności w czasie kompilacji i wykonania (ponosimy pełną
odpowiedzialnośd za jej skutki),
• Stosuje się ją, gdy wiemy z góry, że ani w czasie kompilacji, ani
w czasie wykonania nie będzie możliwe określenie jej sensowności,
• Można, na przykład, dokonad
konwersji char* → int* lub klasaA* → klasaB*, gdzie
klasy klasaA i klasaB są zupełnie niezależne, takie konwersje nie są
bezpieczne,
Dynamic cast
Operator dynamicznego
rzutowania (konwersji) stosuje się, gdy
prawidłowośd przekształcenia nie może byd
sprawdzona na etapie kompilacji (zależy od typu
obiektu klasy polimorficznej), który znany jest
dopiero w czasie wykonania.
Jego użycie ma sens w sytuacjach, gdy mamy do
czynienia z obiektami różnych klas powiązanych
ze sobą hierarchią dziedziczenia.
Dynamic cast
• dynamic_cast<Typ>(wyrazenie)
Typ Typ jest typem wskaźnikowym do polimorficznej klasy pochodnej,
czyli Typ = B*, a wartością wyrażenia wyrazenie jest wskazanie na
obiekt klasy bazowej A, czyli wartośd o typie A*. Operacja rzutowania
polega wtedy na sprawdzeniu, czy obiekt wskazywany
przez wyrazenie jest w rzeczywistości obiektem klasy pochodnej B; po
tym teście wartością całego tego wyrażenia staje się
– wartośd wskaźnikowa typu B* wskazująca na obiekt wskazywany
przez wyrazenie, jeśli test wypadł pomyślnie;
– zero (wskaźnik pusty, NULL), jeśli test się nie powiódł, czyli obiekt
wskazywany przez wyrazenie nie jest obiektem klasy B. Można to
w programie sprawdzid odpowiednim if'em i podjąd stosowne
działania bez przerywania programu.
Dynamic cast
Typ Typ jest typem referencyjnym do polimorficznej klasy pochodnej,
czyli Typ = B&, a wartością wyrażenia wyrazenie jest l-nazwa obiektu
klasy A. Operacja rzutowania polega wtedy na sprawdzeniu, czy
obiekt wyrazenie jest w rzeczywistości obiektem klasy pochodnej B; po
tym teście,
– jeśli wypadł pomyślnie, wartością całego wyrażenia staje się
odniesienie typu B& do obiektu wyrazenie;
– jeśli wypadł niepomyślnie, bo obiekt wyrazenie nie jest typu B, to
zgłaszany jest wyjątek typu bad_cast (z nagłówka typeinfo), który
można przechwycid i podjąd stosowne działania bez przerywania
programu. Tym razem nie można przekazad informacji
o niepowodzeniu zerową wartością wyrażenia, bo nie ma czegoś
takiego jak puste odniesienie (tak jak jest pusty, czyli zerowy,
wskaźnik). Dlatego do obsługi tego przypadku wybrano metodę
zgłoszenia wyjątku.
Dynamic cast
class Program {
protected:
string name;
public:
Program(string n) : name(n) { }
virtual void print() = 0;
virtual ~Program() { }
};
class Freeware : public Program {
public:
Freeware(string n)
Program(n) { }
void print() {
cout << "Free : " << name << endl;
}
};
Dynamic cast
class Shareware : public Program {
int price;
public:
Shareware(string n, int c) : Program(n), price(c) { }
void print() {
cout << "Share: " << name << ", price " << price << endl;
}
int getPrice() {
return price;
}
};
Dynamic cast
int total(Program* prgs[], int size) {
Shareware* sh;
int tot = 0;
for (int i = 0; i < size; ++i) {
prgs[i]->print();
if ( sh = dynamic_cast<Shareware*>(prgs[i]))
tot += sh->getPrice();
}
return tot;
}
Dynamic cast
int main(void) {
Freeware mongodb(„mongodb");
Shareware wz("WinZip",30);
Freeware mysql("MySQL");
Shareware rar("RAR",25);
Program* prgs[] = { &mongodb, &wz, &mysql, &rar };
int tot = total(prgs, sizeof(prgs)/sizeof(prgs[0]));
cout << "\nTotal: $" << tot << endl;
}