250 likes | 419 Views
Sharif University of Technology. C ++ Programming Languages. Lecturer: Omid Jafarinezhad Fall 2013 Lecture 1 C ++ -overview. Department of Computer Engineering. Outline. C++ Overview C++ Design Goals C++ Enhancements Language Features Not Part of C++ Data Hiding Implementation in C
E N D
Sharif University of Technology C++ Programming Languages Lecturer: OmidJafarinezhad Fall 2013 Lecture 1 C++-overview Department of Computer Engineering
Outline C++ Overview C++ Design Goals C++ Enhancements Language Features Not Part of C++ Data Hiding Implementation in C Data Abstraction Implementation in C Data Abstraction Implementation in C++ Exception Handling Implementation in C++
C++ Overview • C++ was designed at AT&T Bell Labs • by BjarneStroustrupin the early 80’s • nearly 30 years ago! • C++ is compatible extension of C that provides: • Stronger type-checking • Support for data abstraction • Support for object-oriented programming • Support for generic programming
C++ Design Goals • As with C, run-time efficiencyis important • Unlike other languages (e.g., Ada, Java, C#, etc.) complicated run-time libraries and virtual machines have not traditionally been required for C++ • Note, that there is no language-specific support for concurrency, persistence, or distribution in C++ • Compatibility with C libraries & traditional development tools • As close to C as possible, but no closer
C++ Enhancements • C++ supports data abstraction & encapsulation • e.g., the class mechanism & name spaces • C++ supports object-oriented programming features • e.g., abstract classes, inheritance, & virtual methods • C++ supports generic programming • e.g., parameterized types • C++ supports sophisticated error handling • e.g., exception handling • C++ supports identifying an object’s type at runtime • e.g., Run-Time Type Identification (RTTI)
Language Features Not Part of C++ Concurrency Persistence Garbage Collection Distribution
Stack Example typedefint T; #define MAX_STACK 100 /* const int MAX_STACK = 100; */ T stack[MAX_STACK]; int top = 0; T item = 10; stack[top++] = item; // push ... item = stack[--top]; // pop Obviously not very abstract...
Data Hiding Implementation in C /* File stack.h*/ /* Type of Stack element. */ typedefintT; /* Stack interface. */ int create (intlen); int destroy (void); void push (Tnew_item); void pop (T *old_top); void top (T *cur_top); intis_empty (void); intis_full (void);
Data Hiding Implementation in C /* File stack.c */ #include "stack.h" staticint top, size; /* Hidden within this file. */ static T *stack; /* Hidden within this file. */ int create (intlen) { top = 0; size = len; stack = malloc (size * sizeof (T)); return stack == 0 ? -1 : 0; } void destroy (void) { free ((void *) stack); } void push (T item) { stack[top++] = item;} void pop (T *item) { *item = stack[--top]; } void top (T *item) { *item = stack[top - 1]; } intis_empty (void) { return top == 0; } intis_full (void) { return top == size; }
Data Hiding Implementation in C • /* File main.c */ • #include "stack.h" • void main(void) { • Ti; • push (10); /* Oops, forgot to call create! */ • push (20); • pop (&i); • destroy (); • } • Use case • Main problems: • The programmer must call create() first & destroy() last! • There is only one stack & only one type of stack
Data Abstraction Implementation in C /* File stack.h*/ typedefint T; typedefstruct { size_t top, size; T *stack; } Stack; intStack_create (Stack *s, size_tlen); voidStack_destroy (Stack *s); voidStack_push (Stack *s, T item); voidStack_pop (Stack *, T *item); /* Must call before pop’ing */ intStack_is_empty (Stack *); /* Must call before push’ing */ intStack_is_full (Stack *); /* ... */
Data Abstraction Implementation in C /* File stack.c */ #include "stack.h" intStack_create (Stack *s, size_tlen) { s->top = 0; s->size = len; s->stack = malloc (size * sizeof (T)); return s->stack == 0 ? -1 : 0; } voidStack_destroy (Stack *s) { free ((void *) s->stack); s->top = 0; s->size = 0; s->stack = 0; } voidStack_push (Stack *s, T item) { s->stack[s->top++] = item; } voidStack_pop (Stack *s, T *item) { *item = s->stack[--s->top]; } intStack_is_empty (Stack *s) { return s->top == 0; }
Data Abstraction Implementation in C • /* File main.c */ • #include "stack.h" • void main(void) { • Stack s1, s2, s3; /* Multiple stacks! */ • T item; • Stack_pop (&s2, &item); /* Pop from empty stack */ • /* Forgot to call Stack_create! */ • Stack_push (&s3, 10); • s2 = s3; /* Disaster due to aliasing!!! */ • /* Destroy uninitialized stacks! */ • Stack_destroy (&s1); Stack_destroy (&s2); • } • Main problems: • No guaranteed initialization, termination, or assignment • Still only one type of stack supported • No generalized error handling... • The C compiler does not enforce information hiding e.g., • s1.top = s2.stack[0]; /* Violate abstraction */ • s2.size = s3.top; /* Violate abstraction */ Use case
Data Abstraction Implementation in C++ //2D point class. file: “Point.h” class Point { double x_coord; double y_coord; // Data-members public: Point(); // Constructors Point(double x, double y); ~Point(); // Destructor double getX(); // Accessors double getY(); void setX(double x); // Mutators void setY(double y); }; /* File stack.h*/ typedefintT; classStack{ public: Stack (size_t size); Stack (const Stack &s); voidoperator= (const Stack &); ~Stack (void); void push (const T &item); void pop (T &item); boolis_empty (void); boolis_full (void); private: size_t top, size; T *stack; }; We can get encapsulation and more than one stack:
Data Abstraction Implementation in C++ • /* File stack.cpp */ • #include "stack.h" • Stack::Stack (size_t s): top(0), size(s), stack(new T[s]) {} • Stack::Stack (const Stack &s) • : top (s.top), size (s.size), stack (new T[s.size]) • { • for (size_ti = 0; i < s.size; ++i) stack[i] = s.stack[i]; • } • void Stack::operator= (const Stack &s) { • if (this == &s) return; • T *temp_stack = new T[s.size]; • delete [] stack; stack = 0; • for (size_ti = 0; i < s.size; ++i) temp_stack[i] = s.stack[i]; • stack = temp_stack; top = s.top; size = s.size; • } • Stack::~Stack (void) { delete [] stack; } • boolStack::is_empty(void) { return top == 0; } • boolStack::is_full (void) { return top == size; } • voidStack::push (const T &item) { stack[top++] = item; } • voidStack::pop (T &item) { item = stack[--top]; }
Data Abstraction Implementation in C++ • /* File main.c */ • #include "stack.h" • void main(void) { • Stack s1 (1), s2 (100); • T item; • if (!s1.is_full ()) • s1.push (473); • if (!s2.is_full ()) • s2.push (2112); • if (!s2.is_empty ()) • s2.pop (item); • // Access violation caught at compile-time! • s2.top = 10; • // Termination is handled automatically. • } Use case
Benefits of C++ DAT • Data hiding & data abstraction, e.g., Stack s1 (200); s1.top = 10 // Error flagged by compiler! • The ability to declare multiple stack objects Stack s1 (10), s2 (20), s3 (30); • Automatic initialization & termination { Stack s1 (1000); // constructor called automatically. // ... // Destructor called automatically }
Drawbacks of C++ DAT • Error handling is obtrusive • use exception handling to solve this (but be careful)! • The example is limited to a single type of stack element (int in this case) • use parameterized types to remove this limitation • Function call overhead • use inline functions to remove this overhead
Exception Handling Implementation in C++ • /* File stack.h*/ • typedefintT; • classStack{ • public: • class Underflow { /* ... */ }; // WARNING: be cautious when using • class Overflow { /* ... */ }; // exception specifiers... • Stack (size_t size); • Stack (const Stack &s); • void operator= (const Stack &); • ~Stack (void); • void push (const T &item) throw (Overflow); • void pop (T &item) throw (Underflow); • boolis_empty (void); • boolis_full (void); • private: • size_t top, size; • T *stack; • };
Exception Handling Implementation in C++ • /* File stack.cpp */ • #include "stack.h" • Stack::Stack (size_t s): top(0), size(s) { /*stack = allocate…*/} • … • void Stack::push (const T &item) throw(Stack::Overflow) • { • if (is_full ()) throw Stack::Overflow (); // guard condition • stack[top++] = item; • } • void Stack::pop (T &item) throw(Stack::Underflow) • { • if (is_empty ()) throwStack::Underflow (); • item = stack[--top]; • } • …
Exception Handling Implementation in C++ • /* File main.c */ • #include "stack.h" • void main(void) { • Stack s1 (1), s2 (100); • try • { • T item; • s1.push (473); • s1.push (42); // Exception, full stack! • s2.pop (item); // Exception, empty stack! • s2.top = 10; // Access violation caught! • } • catch (Stack::Underflow) { /* Handle underflow... */ } • catch (Stack::Overflow) { /* Handle overflow... */ } • catch (...) { /* Catch anything else... */ throw; } • } Use case
Template Implementation in C++ • /* File stack.h*/ • template <typename T> • class Stack { • public: • Stack (size_t size); • Stack (const Stack<T> &rhs); • voidoperator= (const Stack<T> &rhs); • ~Stack (void) • void push (const T &item); • void pop (T &item); • boolis_empty (void); • boolis_full (void); • private: • size_t top, size; • T *stack; • };
Template Implementation in C++ /* File stack.c*/ template <typename T> Stack<T>::Stack (size_t size) : top (0), size (size){/* allocate */ } template <typename T> Stack<T>::~Stack (void) { /* free*/ } template <typename T> void Stack<T>::push (const T &item) { stack[top++] = item; } template <typename T> void Stack<T>::pop (T &item) { item = stack[--top]; } // ...
Template Implementation in C++ • /* File main.c */ • #include "stack.h" • void main(void) { • Stack<int> s1 (1000); • Stack<float> s2; • s1.push (-291); • s2.top = 3.1416; // Access violation caught! • } Use case