C-overview4 - An Overview of C Douglas C Schmidt C Overview An Overview of C Douglas C Schmidt Professor [email protected]

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: An Overview of C++ Douglas C. Schmidt C++ Overview An Overview of C++ Douglas C. Schmidt Professor [email protected] www.dre.vanderbilt.edu/schmidt/ Department of EECS Vanderbilt University (615) 343-8197 C++ was designed at AT&T Bell Labs by Bjarne Stroustrup in the early 80's nearly 30 years ago! The original cfront translated C++ into C for portability However, this was difficult to debug and potentially inefficient Many native host machine compilers now exist e.g., C++ Builder, clang, Comeau C/C++, GCC, Intel C++ Compiler, Microsoft Visual C++, Sun Studio, etc. C++ is a mostly upwardly compatible extension of C that provides: www.dre.vanderbilt.edu/schmidt/PDF/C++-overview.pdf January 18, 2012 1. 2. 3. 4. Stronger typechecking Support for data abstraction Support for object-oriented programming Support for generic programming Vanderbilt University 1 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt C++ Design Goals As with C, run-time efficiency is 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 is emphasized, e.g., Object code reuse The storage layout of structures is compatible with C e.g., support for X-windows, standard ANSI C library, & UNIX/WIN32 system calls via extern block C++ works with the make recompilation utility Vanderbilt University 2 C++ Design Goals (cont'd) "As close to C as possible, but no closer" i.e., C++ is not a proper superset of C backwards compatibility is not entirely maintained Typically not a problem in practice... Note, certain C++ design goals conflict with modern techniques for: 1. Compiler optimization e.g., pointers to arbitrary memory locations complicate register allocation & garbage collection 2. Software engineering e.g., separate compilation complicates inlining due to difficulty of interprocedural analysis Dynamic memory management is error-prone Vanderbilt University 3 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Major C++ Enhancements 1. C++ supports data abstraction & encapsulation e.g., the class mechanism & name spaces 2. C++ supports object-oriented programming features e.g., abstract classes, inheritance, & virtual methods 3. C++ supports generic programming e.g., parameterized types 4. C++ supports sophisticated error handling e.g., exception handling 5. C++ supports identifying an object's type at runtime e.g., Run-Time Type Identification (RTTI) Vanderbilt University 4 Important Minor C++ Enhancements C++ enforces type checking via function prototypes Provides type-safe linkage Provides inline function expansion Declare constants that can be used to define static array bounds with the const type qualifier Built-in dynamic memory management via new & delete operators Namespace control Vanderbilt University 5 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Useful Minor C++ Enhancements The name of a struct, class, enum, or union is a type name References allow "call-by-reference" parameter modes New type-secure extensible iostreams I/O mechanism "Function call"-style cast notation Several different commenting styles New mutable type qualifier New bool boolean type Questionable C++ Features Default values for function parameters Operator & function overloading Variable declarations may occur anywhere statements may appear within a block Allows user-defined conversion operators Static data initializers may be arbitrary expressions Vanderbilt University 6 Vanderbilt University 7 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Language Features Not Part of C++ 1. Concurrency "Concurrent C" by Gehani Actor++ model by Lavender & Kafura 2. Persistence Object Store, Versant, Objectivity Exodus system & E programming language 3. Garbage Collection USENIX C++ 1994 paper by Ellis & Detlefs GNU g++ 4. Distribution CORBA, DDS, COM+, SOAP, etc. Vanderbilt University 8 Vanderbilt University Strategies for Learning C++ Focus on concepts & programming techniques Don't get lost in language features Learn C++ to become a better programmer More effective at designing & implementing Design Patterns C++ supports many different programming styles Learn C++ gradually Don't have to know every detail of C++ to write a good C++ program 9 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Stack Example The following slides examine several alterative methods of implementing a Stack Begin with C & evolve up to various C++ implementations First, consider the "bare-bones" implementation: typedef int 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 Data Hiding Implementation in C Define the interface to a Stack of integers in C in Stack.h: /* Type of Stack element. */ typedef int T; /* Stack interface. */ int create (int size); int destroy (void); void push (T new_item); void pop (T *old_top); void top (T *cur_top); int is_empty (void); int is_full (void); Obviously not very abstract... Vanderbilt University 10 Vanderbilt University 11 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Data Hiding Implementation in C (cont'd) /* File stack.c */ #include "stack.h" static int top_, size_; /* Hidden within this file. */ static T *stack_; int create (int size) { top_ = 0; size_ = size; 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]; } int is_empty (void) { return top_ == 0; } int is_full (void) { return top_ == size_; } Data Hiding Implementation in C (cont'd) Use case #include "stack.h" void foo (void) { T i; push (10); /* Oops, forgot to call create! */ push (20); pop (&i); destroy (); } Main problems: 1. 2. 3. 4. 12 The programmer must call create() first & destroy() last! There is only one stack & only one type of stack Name space pollution... Non-reentrant 13 Vanderbilt University Vanderbilt University An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Data Abstraction Implementation in C An ADT Stack interface in C: typedef int T; typedef struct { size_t top_, size_; T *stack_; } Stack; int Stack_create (Stack *s, size_t size); void Stack_destroy (Stack *s); void Stack_push (Stack *s, T item); void Stack_pop (Stack *, T *item); /* Must call before pop'ing */ int Stack_is_empty (Stack *); /* Must call before push'ing */ int Stack_is_full (Stack *); /* ... */ Data Abstraction Implementation in C (cont'd) An ADT Stack implementation in C: #include "stack.h" int Stack_create (Stack *s, size_t size) { s->top_ = 0; s->size_ = size; s->stack_ = malloc (size * sizeof (T)); return s->stack_ == 0 ? -1 : 0; } void Stack_destroy (Stack *s) { free ((void *) s->stack_); s->top_ = 0; s->size_ = 0; s->stack_ = 0; } void Stack_push (Stack *s, T item) { s->stack_[s->top_++] = item; } void Stack_pop (Stack *s, T *item) { *item = s->stack_[--s->top_]; } int Stack_is_empty (Stack *s) { return s->top_ == 0; } Vanderbilt University 14 Vanderbilt University 15 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Data Abstraction Implementation in C (cont'd) Use case void foo (void) { Stack s1, s2, s3; /* Multiple stacks! */ T item; Stack_pop (&s2, &item); /* Pop'd 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 with Data Abstraction in C 1. No guaranteed initialization, termination, or assignment 2. Still only one type of stack supported 3. Too much overhead due to function calls 4. No generalized error handling... 5. The C compiler does not enforce information hiding e.g., s1.top_ = s2.stack_[0]; /* Violate abstraction */ s2.size_ = s3.top_; /* Violate abstraction */ Vanderbilt University 16 Vanderbilt University 17 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Data Abstraction Implementation in C++ We can get encapsulation and more than one stack: typedef int T; class Stack { public: Stack (size_t size); Stack (const Stack &s); void operator= (const Stack &); ~Stack (void); void push (const T &item); void pop (T &item); bool is_empty (void) const; bool is_full (void) const; private: size_t top_, size_; T *stack_; }; Data Abstraction Implementation in C++ (cont'd) Manager operations 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_t i = 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_t i = 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_; } Vanderbilt University 18 Vanderbilt University 19 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Data Abstraction Implementation in C++ (cont'd) Accessor & worker operations bool Stack::is_empty (void) const { return top_ == 0; } bool Stack::is_full (void) const { return top_ == size_; } void Stack::push (const T &item) { stack_[top_++] = item; } void Stack::pop (T &item) { item = stack_[--top_]; } Data Abstraction Implementation in C++ (cont'd) Use case #include "Stack.h" void foo (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. } Vanderbilt University 20 Vanderbilt University 21 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Benefits of C++ Data Abstraction Implemenation 1. Data hiding & data abstraction, e.g., Stack s1 (200); s1.top_ = 10 // Error flagged by compiler! Drawbacks with C++ Data Abstraction Implementation 1. Error handling is obtrusive Use exception handling to solve this (but be careful)! 2. The example is limited to a single type of stack element (int in this case) We can use C++ "parameterized types" to remove this limitation 3. Function call overhead We can use C++ inline functions to remove this overhead 2. The ability to declare multiple stack objects Stack s1 (10), s2 (20), s3 (30); 3. Automatic initialization & termination { Stack s1 (1000); // constructor called automatically. // ... // Destructor called automatically } Vanderbilt University 22 Vanderbilt University 23 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt C++ exceptions separate error handling from normal processing Exception Handling Implementation in C++ (cont'd) typedef .... T; // Where "...." is a placeholder for any C++ type. class Stack { public: class Underflow { /* ... */ }; // WARNING: be cautious when using class Overflow { /* ... */ }; // exception specifiers... Stack (size_t size); Stack (const Stack &rhs); void operator= (const Stack &rhs); ~Stack (void); void push (const T &item) throw (Overflow); void pop (T &item) throw (Underflow); // ... private: size_t top_, size_; T *stack_; }; Exception Handling Implementation in C++ (cont'd) Stack.cpp Stack::Stack (size_t s): top_ (s), size_ (s), stack_ (new T[s]) {} Stack::~Stack () { delete stack_; } void Stack::push (const T &item) throw (Stack::Overflow) { if (is_full ()) throw Stack::Overflow (); stack_[top_++] = item; } void Stack::pop (T &item) throw (Stack::Underflow) { if (is_empty ()) throw Stack::Underflow (); item = stack_[--top_]; } Vanderbilt University 24 Vanderbilt University 25 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Exception Handling Implementation in C++ (cont'd) Stack.cpp Stack::Stack (const Stack &s): : top_ (s.top_), size_ (s.size_), stack_ (0) { scoped_array<T> temp_stack (new T[s.size_]); for (size_t i = 0; i < s.size_; ++i) temp_stack[i] = s.stack_[i]; temp_stack.swap (stack_); } void Stack::operator= (const Stack &s) { if (this == &s) return; // Check for self-assignment scoped_array<T> temp_stack (new T[s.size_]); for (size_t i = 0; i < s.size_; ++i) temp_stack[i] = s.stack_[i]; top_ = s.top_; size_ = s.size_; temp_stack.swap (stack_); } Exception Handling Implementation in C++ (cont'd) scoped array extends auto ptr to destroy built-in arrays template <typename T> class scoped_array { public: explicit scoped_array (T *p = 0) : ptr_ (p) {} ~scoped_array () { delete ptr_; } T &operator(std::ptrdiff_t i) const { return ptr_[i]; } T *get() const { return ptr_; } void swap (T *&b) { T *tmp = b; b = ptr_; ptr_ = tmp; } void swap (scoped_array<T> &b) { T *tmp = b.ptr_; b.ptr_ = this->ptr_; this->ptr_ = tmp; } private: T *ptr_; scoped_array (const scoped_array<T> &); scoped_array &operator=(const scoped_array<T> &); }; Vanderbilt University 26 Vanderbilt University 27 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Exception Handling Implementation in C++ (cont'd) There's a better way to implement operator=(): void Stack::operator= (const Stack &s) { if (this == &s) return; // Check for self-assignment Stack t (s); std::swap (t.top_, top_); std::swap (t.size_, size_); std::swap (t.stack_, stack_); } // Old way: void Stack::operator= (const Stack &s) { if (this == &s) return; // Check for self-assignment scoped_array<T> temp_stack (new T[s.size_]); for (size_t i = 0; i < s.size_; ++i) temp_stack[i] = s.stack_[i]; top_ = s.top_; size_ = s.size_; temp_stack.swap (stack_); } Exception Handling Implementation in C++ (cont'd) And yet an even better way to implement exception-safe Stack: class Stack { // ... private: // ... scoped_array<T> stack_; void swap (Stack &); }; // ... Stack::Stack (const Stack &s) : top_ (s.top_), size_ (s.size_), stack_ (new T[s.size_]) { for (size_t i = 0; i < s.size_; ++i) stack_[i] = s.stack_[i]; } Stack::~Stack () { /* no-op! */ } Vanderbilt University 28 Vanderbilt University 29 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Exception Handling Implementation in C++ (cont'd) And yet an even better way to implement operator=(): void Stack::operator= (const Stack &s) { if (this == &s) return; // Check for self-assignment Stack temp_stack (s); swap (temp_stack); } void Stack::swap (Stack &t) { std::swap (t.top_, top_); std::swap (t.size_, size_); t.stack_.swap (stack_); } Exception Handling Implementation in C++ (cont'd) Use case #include "Stack.h" void foo (void) { Stack s1 (1), s2 (100); try { T item; s1.push (473); s1.push (42); // Exception, push'd full stack! s2.pop (item); // Exception, pop'd empty stack! s2.top_ = 10; // Access violation caught! } catch (Stack::Underflow) { /* Handle underflow... */ } catch (Stack::Overflow) { /* Handle overflow... */ } catch (...) { /* Catch anything else... */ throw; } } // Termination is handled automatically. } This solution is easy to generalize! Vanderbilt University 30 Vanderbilt University 31 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Template Implementation in C++ A parameterized type Stack class interface using C++ template <typename T> class Stack { public: Stack (size_t size); Stack (const Stack<T> &rhs); void operator= (const Stack<T> &rhs); ~Stack (void) void push (const T &item); void pop (T &item); bool is_empty (void) const; bool is_full (void) const; private: size_t top_, size_; scoped_array<T> stack_; void swap (scoped_array<T> &t); }; Template Implementation in C++ (cont'd) A parameterized type Stack class implementation using C++ template <typename T> inline Stack<T>::Stack (size_t size) : top_ (0), size_ (size), stack_ (new T[size]) { } template <typename T> inline Stack<T>::~Stack (void) { /* no-op! */ } template <typename T> inline void Stack<T>::push (const T &item) { stack_[top_++] = item; } template <typename T> inline void Stack<T>::pop (T &item) { item = stack_[--top_]; } // ... Vanderbilt University 32 Vanderbilt University 33 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Template Implementation in C++ (cont'd) Note minor changes to accommodate parameterized types #include "Stack.h" void foo (void) { Stack<int> s1 (1000); Stack<float> s2; Stack< Stack <Activation_Record> *> s3; s1.push (-291); s2.top_ = 3.1416; // Access violation caught! s3.push (new Stack<Activation_Record>); Stack <Activation_Record> *sar; s3.pop (sar); delete sar; // Termination of s1, s2, & s3 handled automatically } Template Implementation in C++ (cont'd) Another parameterized type Stack class template <typename T, size_t SIZE> class Stack { public: Stack (void); ~Stack (void) void push (const T &item); void pop (T &item); private: size_t top_, size_; T stack_[SIZE]; }; No need for dynamic memory, though SIZE must be const, e.g., Stack<int, 200> s1; Vanderbilt University 34 Vanderbilt University 35 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Object-Oriented Implementation in C++ Problems with previous examples: Changes to the implementation will require recompilation & relinking of clients Extensions will require access to the source code Solutions Combine inheritance with dynamic binding to completely decouple interface from implementation & binding time This requires the use of C++ abstract base classes Object-Oriented Implementation in C++ (cont'd) Defining an abstract base class in C++ template <typename T> class Stack { public: virtual ~Stack (void) = 0; // Need implementation! virtual void push (const T &item) = 0; virtual void pop (T &item) = 0; virtual bool is_empty (void) const = 0; virtual bool is_full (void) const = 0; void top (T &item) { /* Template Method */ pop (item); push (item); } }; By using "pure virtual methods," we can guarantee that the compiler won't allow instantiation! Vanderbilt University 36 Vanderbilt University 37 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Inherit to create a specialized stack implemented via an STL vector: #include "Stack.h" #include <vector> template <typename T> class V_Stack : public Stack<T> { public: enum { DEFAULT_SIZE = 100 }; V_Stack (size_t size = DEFAULT_SIZE); V_Stack (const V_Stack &rhs); virtual void push (const T &item); virtual void pop (T &item); virtual bool is_empty (void) const; virtual bool is_full (void) const; private: size_t top_; std::vector<T> stack_; }; Object-Oriented Implementation in C++ (cont'd) Object-Oriented Implementation in C++ (cont'd) class V Stack implementation template <typename T> V_Stack<T>::V_Stack (size_t size): top_ (0), stack_ (size) {} template <typename T> V_Stack<T>::V_Stack (const V_Stack &rhs): top_ (rhs.top_), stack_ (rhs.stack_) {} template <typename T> void V_Stack<T>::push (const T &item) { stack_[top_++] = item; } template <typename T> void V_Stack<T>::pop (T &item) { item = stack_[--top_]; } template <typename T> int V_Stack<T>::is_full (void) const { return top_ >= stack_.size (); } Vanderbilt University 38 Vanderbilt University 39 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Object-Oriented Implementation in C++ (cont'd) Inheritance can also create an linked list stack: template <typename T> class Node; // forward declaration. template <typename T> class L_Stack : public Stack<T> { public: enum { DEFAULT_SIZE = 100 }; L_Stack (size_t hint = DEFAULT_SIZE); ~L_Stack (void); virtual void push (const T &new_item); virtual void pop (T &top_item); virtual bool is_empty (void) const { return head_ == 0; } virtual bool is_full (void) const { return 0; } private: // Head of linked list of Node<T>'s. Node<T> *head_; }; Object-Oriented Implementation in C++ (cont'd) class Node implementation template <typename T> class Node { friend template <typename T> class L_Stack; public: Node (T i, Node<T> *n = 0): item_ (i), next_ (n) {} private: T item_; Node<T> *next_; }; Note that the use of the "Cheshire cat" idiom allows the library writer to completely hide the representation of class V Stack... Vanderbilt University 40 Vanderbilt University 41 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Object-Oriented Implementation in C++ (cont'd) class L Stack implementation: template <typename T> L_Stack<T>::L_Stack (size_t): head_ (0) {} template <typename T> void L_Stack<T>::push (const T &item) { Node<T> *t = new Node<T> (item, head_); head_ = t; } template <typename T> void L_Stack<T>::pop (T &top_item) { top_item = head_->item_; Node<T> *t = head_; head_ = head_->next_; delete t; } template <typename T> L_Stack<T>::~L_Stack (void) { for (T t; head_ != 0; pop (t)) continue; } Object-Oriented Implementation in C++ (cont'd) Using our abstract base class, it is possible to write code that does not depend on the stack implementation, e.g., Stack<int> *make_stack (bool use_V_Stack) { return use_V_Stack ? new V_Stack<int> : new L_Stack<int>; } void print_top (Stack<int> *stack) { std::cout << "top = " << stack->top () << std::endl; } int main (int argc, char **) { std::auto_ptr <Stack<int>> sp (make_stack (argc > 1)); sp->push (10); print_top (sp.get ()); } Vanderbilt University 42 Vanderbilt University 43 An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt Object-Oriented Implementation in C++ (cont'd) Moreover, we can make changes at run-time without modifying, recompiling, or relinking existing code via dynamic linking: char stack_symbol[MAXNAMLEN]; char stack_file[MAXNAMLEN]; cin >> stack_file >> stack_factory; void *handle = ACE_OS::dlopen (stack_file); Stack<int> *(*factory)(bool) = ACE_OS::dlsym (handle, stack_factory); std::auto_ptr <Stack<int>> sp ((*factory) (argc > 1)); sp->push (10); print_top (sp.get ()); The modifications for C++ involve both the core language and the standard library: Prefer introduction of new features through the standard library, rather than extending the core language Improve C++ to facilitate systems and library design, rather than to introduce new features only useful to specific applications; Increase type safety by providing safer alternatives to current, unsafe techniques; Increase performance and the ability to work directly with hardware; Implement "zero-overhead" principle (additional support required by some utilities must be used only if the utility is used) Make C++ easier to teach and to learn without removing any utility needed by expert programmers. 44 Vanderbilt University 45 The Road Ahead: C++11 Note, no need to stop, modify, & restart an executing application! Naturally, this requires careful configuration management... Vanderbilt University An Overview of C++ Douglas C. Schmidt An Overview of C++ Douglas C. Schmidt C++11 Example #include #include #include #include <iostream> <iterator> <vector> <algorithm> Summary A major contribution of C++ is its support for defining abstract data types (ADTs) & for generic programming e.g., classes, parameterized types, & exception handling int main () { std::vector<int> v ({10, 20, 30, 40}); for (int &i : v) std::cout << i << std::endl; auto total = 0; std::for_each (v.begin (), v.end (), [&total](int x) { total += x; }); std::cout << total << std::endl; return 0; } Vanderbilt University 46 For some systems, C++'s ADT support is more important than using the OO features of the language For other systems, the use of C++'s OO features is essential to build highly flexible & extensible software e.g., inheritance, dynamic binding, & RTTI Vanderbilt University 47 ...
View Full Document

This note was uploaded on 02/27/2012 for the course CS 251 taught by Professor Staff during the Fall '08 term at Purdue University-West Lafayette.

Ask a homework question - tutors are online