560 likes | 572 Views
Introduction to C++. Jie Chen High Performance Computing Group chen@jlab.org http://www.jlab.org/~chen/teaching/C++Intro.ppt. Organization. Introduction. Classes and Object-oriented Programming. Advanced Features of C++. Interesting Topics of C++. Optimizing your programs. History.
E N D
Introduction to C++ Jie Chen High Performance Computing Group chen@jlab.org http://www.jlab.org/~chen/teaching/C++Intro.ppt
Organization • Introduction. • Classes and Object-oriented Programming. • Advanced Features of C++. • Interesting Topics of C++. • Optimizing your programs.
History • Bjarne Stroustrup, AT&T Labs • 1980: “C with Classes” • Improve program structure (Simula67) • Maintain run-time efficiency • Support rather than enforce effective programming techniques • 1985: C++ 1.0 • 1995: Draft standard
ISO/IEC 14882 • 1998: International standardization • New type bool • static_cast, dynamic_cast etc • Run-Time Type Information (RTTI) • “Standard Library” (STL) • Generic containers • Generic algorithms • Compatibility with ANSI C • Greater Portability
What is C++ ? • General purpose, biased towards systems programming: • A better C • Supports data abstraction • Supports object-oriented programming • Supports generic programming (from: The C++ Programming Language, third ed.)
A better C • Strong static typing • Symbolic constants • Inline code substitution • Default function arguments • Function and operator overloading • References • Namespace management • Exception Handling • Template
Data Abstraction (encapsulation) • Define program entity in terms of related data. • Define operations on entity. • Separate implementation of program entity from its interface (data hiding). • Program relies on abstract properties of entity
Object-Oriented Programming • Extends data abstraction • Facilitates code reuse through inheritance • Runtime dynamic binding • C++ is not “truly object-oriented” • hybrid approach • Not everything is a class
The Domain of C++ • Operating system kernels and components* • Device drivers* • Real-time / deterministic systems • Critical systems • Parallel computing • Numerical calculations • 3-D Games and Graphics.
Key features • Classes, single / multiple inheritance • Streamed I/O • Exceptions • Templates • Namespaces* • Run-time type information* • Standard library*
C++ Syntax Features Something you don’t have in C • A reference is an alias (an alternate name) for an object. int a = 1; int c = 10; int& b = a; int& d; // error int* dd; // ok • References are frequently used for pass-by-reference • void swap(int& i, int& j) { int tmp = i; i = j; j = tmp; } int main() { int x, y;// ... swap(x,y); } You can't separate the reference from the referent Use references when you can, and pointers when you have to
C++ Syntax Featuressomething you don’t have in C • Symbolic constants* const int arraySize = 10; int a[arraySize]; • Inline functions • A C++ compiler generates a copy of an inline function in place to avoid function call. • Good for small functions. inline float cube (const float s) {return s*s*s;} • Default function arguments • void foo (int a, int b = 0) • int a, b; • foo (a, b); foo (a); // called foo function with arguments (a, 0)
C style structure struct point { int x; int y; }; struct point { unsigned int r; unsigned int theta; }; C++ class class point { public: point (void); ~point (void); int getX (void) const; int getY (void) const; unsigned int getR (void) const; unsigned int getTheta (void) const; private: int x_; int y_; }; A class definition is in a header file: .h file A class implementation is in a .cc, .cpp, .cxx file Classes and Data Abstraction
Classes #include <stdio.h> #include <stdlib.h> #include “point.h” point::point(void) {x_ = 0; y_ = 0;} point::~point (void) {// empty} int point::getX (void) const {return x_;} int point::getY (void) const {return y_;} unsigned int point::getR (void) const {return sqrt(x_* x_ + y_ * y_);}
Classes • Constructors and destructor • Object is an instance of a class. • A constructor initializes members of an object. • point::point(void) {x_ = 0; y_ = 0;} • A class can have multiple constructors. • A default constructor is a constructor that can be called with no arguments. • Destructors are used to release any resources allocated by an object. • ~point (void)
Classes • Instantiation { point a; // create an object. Constructor called } // The object is destroyed. point* b = new point (); • create an object which will not be destroyed unless delete is called. delete b;
Classes • Accessing Class Members point a; int x = a.getX(); // ok int xx = a.x_; // no good point* b = new point (); int y = b->getY (); // ok int yy = b->y_; // no good
Classes • Function and Operator Overloading • Function overloading • class point { public: double distance (const point& b); // distance to b double distance (void); // distance to (0,0) }; double d = a.distance (b); double d0 = a.distance (); • Operator overloading matrix operator * (const matrix& b); matrix c = a * b; <==> (c = a.operator* (b))
class employee { public: employee (const char* name); virtual ~employee (void); void info (void) const {cout << name;} double getPay (void) const; protected: unsigned int employeeId (void); private: char* name; }; class hourlyWorker : public employee { void info (void) const {cout<<“hourlyWorker “ << name;} float hoursWorked (void) const; }; Classes and Inheritance employee regularWorker hourlyWorker hourlyWorker is a derived class of employee employ is a base class of hourlyWorker hourlyWorker h(“joe”); Employee* e = &h; // safe
base virtual func (void) derived virtual func (void) Virtual functions and polymorphism • Polymorphism Objects of different classes related by inheritance respond to the same message differently. • Polymorphism and virtual functions A request made through a base-class pointer (reference) to use virtual function will be dispatched to a correct overridden function in the derived class associated with the object. base* a a->func() base* b b->func()
Virtual functions and Polymorphism • Non-virtual class member functions employee* e = new employee (“joe smith”); hourlyWorker *h = new hourlyWorker (“john doe”); e->info (); // call base-class info function “joe smith” h->info (); // call derived class info function “hourlyWorker john doe” e = h; // allowable implicit conversion e->info(); // still call base class info function “john doe” • Virtual class member functions: { virtual void info (void) const; } e->info (); // call derived class info function “hourlyWorker john doe” employee* ee[num_employees]; for (int m = 0; m < num_employees; m++) ee[m]->info (); // different info functions called
C++ I/O Stream Why using I/O stream instead of using faithful printf and scanf? Type-safe object being I/O'd is known statically Less error prone no redundant "%" tokens that have to be consistent with the actual objects being I/O'd Extensible New classes can define own I/O stream behavior Inheritable New stream classes can be derived
All primitive types are supported for I/O stream int x, y; x = 8; std::cin >> y; std::cout << x << “ “ << y; char input[32]; std::cin >> input; std::cout << input; C++ I/O Stream ios istream ostream ifstream iostream ofstream fstream std::cin std::cout std::cerr
C++ I/O Stream • Define I/O behavior for a class friend ostream& operator << (ostream& os, const point& p); friend istream& operator >> (istream& os, point& p); ostream& operator << (ostream& os, const point& p) { return os << p.x_ << “ “ << p.y_; } istream& operator >> (istream& is, point& p) { return is >> p.x_ >> p.y_; } point p; std::cin >> p; // read two integers from keyboard.
Introduction to C++ (Part 2) • Summary of part one • C++ Language Features • References • Inline functions • Symbolic constants • Default arguments for functions • C++ Classes • Constructors/destructor • Class instantiation • Inheritance • Function and operator overloading • Virtual functions and polymorphism • I/O stream
Exceptions • Signify errors cleanly • Equivalent to exiting scope • Avoids overloading return values • Handle errors at appropriate level • Exception propagates up call stack until “caught”. • Convey useful information to handler • Error class • Error details
Defining Exceptions • An exception is just an object class base_error { public: const char * s; error (const char * _s = 0); virtual const char * what () { return s; } }; class range_error : public base_error { public: const double x; range_error (double _x) : x(_x) {} const char * what () { … // construct and return message } }; class system_error : public base_error { public: const int errno; system_error (int _errno, const char * s = 0) : errno(_errno) {} const char * what () { … // return system error message } }; }
Throwing Exceptions • Raise an exception by using the keyword “throw” double average_grades (istream & in) { double x; double S = 0; int n = 0; while (in >> x) { if (x < 0 || x > 100) throw range_error (x); S += x; n++; } if (n == 0) throw base_error (“empty input file”); return S / n; }
Catching Exceptions • Catch an exception via a “try..catch” block int main (int, char *[]) { using namespace std; try { cout << “average: “ << average_grades(cin) << endl; } catch (range_error & e) { cerr << “encountered a peculiar grade: ” << e.x << endl; exit (1); } catch (error & e) { cerr << “unable to calculate averages: “ << e.what() << endl; exit (2); } return 0; }
Templates • Parameterized classes template <class A > class list { list (); virtual ~list (); add (A value); }; • Utility functions template <class T> const T & min (const T & a, const T & b) { return (a < b? a : b); } • A C++ compiler will generate separate classes for different classes that are passed as parameters for a template class or a template function list < int > intlist (); intlist.add (1); list < double> dlist (); dlist.add (3.423); int a, b, c; a = 1; b = 2; c = min (a, b);
Template Practicalities • Reuse the same code for different data types. • Include code in header files. • Excessive use of templates causes: • Object code bloat • Difficult to maintain source code
Namespaces* • Explicitly partition globally-scoped type definitions and variable names into logical segments • avoid name conflicts namespacemy { const double version = 1.1; class string {…}; class vector {…}; } namespaceyour { const int version = 3; class string {…}; class vector {…}; }
Using Namespaces • Import namespace into scope using namespace my; string s; // implicitly use my::string • Import individual symbols into scope use my::string; use your::vector; string s; // my::string vector v; // your::vector • Explicitly qualify symbols my::string s; your::vector v;
Run-time Type Information* • Casting • Dynamic_cast • Static_cast • Const_cast • Reinterpret_cast • Typeid • Type id information is used to support dynamic_cast operations • Rarely used directly
pd = (D *)pb Dynamic_cast • Safe mechanism for obtaining derived class from base class (“downcasting”) class B { //… }; class D : public B { //… }; void f (B * pb) { D* pd = dynamic_cast < D * >(pb); if (pd) { // guranteed that pb is a D * } }
Other casts • static_cast • dynamic_cast, without run-time check double d = 8.22; int x = static_cast< int >(d); • reinterpret_cast • Equivalent to C-style cast • Inherently unsafe and non-portable • const_cast • Cast away const modifier. • Results undefined if object really is const
Standard Library* • Containers • Iterators • Algorithms • Diagnostics • Strings • I/O • Localization • Language support • Numerics
Standard Library practicalities • All symbols from the standard library are in namespace std. • Header files lack trailing “.h” #include <string> #include <list> #include <iostream> int main (int argc, char * argv[]) { using namespace std; vector<string> args; for (int i = 0; i < argc; i++) args.push_back (argc[i]); for (vector<string>::iterator arg = args.begin() arg != args.end(); ++arg) cout << *arg << endl; }
Strings • Vast improvement over C-style strings • Transform C-style string via c_str() method.
C library • Access C runtime library by removing “.h” from header files, and prepending “c” #include <cstring> // strcmp, strlen, etc. #include <cstdio> // printf, scanf, etc. #include <cerrno> // errno, strerror, etc. #include <cctype> // isalnum, isdigit, etc. #include <cstdlib> // malloc, free, etc. // etc.
Interesting topics • Calling C functions from C++ extern "C" void f (int i, char c, float x); • Allow C++ functions to be called from C // This is C++ code // Declare f(int,char,float) using extern C: extern "C" void f(int i, char c, float x); // ... // Define f(int,char,float) in some C++ module void f(int i, char c, float x){ // ... }
Interesting Topics • Const correctness • const Fred* p • p cannot be used to change an object p pointing to • Fred* const p • Pointer value of p cannot be changed, but the object p pointing to can be changed • const Fred* const p • Nothing can be changed. • const Fred& p • p cannot be used to change an object that p is referencing
Interesting Topics • friend of a class • friend can access private section of a class. Class A{ private: friend class B; int a, b, c; }; • Friendship is not inheritable
Interesting Topics • Big Three • Class A { public: A (void); // Default constructor A (const A& a); // Copy constructor A& operator = (const A& a); // Assignment operator }; void foo (A a); A a[10]; // default constructor called 10 time A a, b; // default constructor called 2 times foo (a); // copy constructor called b = a; // assignment operator called
Interesting Topics • Virtual destructor • Always declare destructor virtual when a class can be derived class base { public: virtual ~base(); }; • A correct destructor will be called when an object of derived classes is deleted.
Designing with C++ • Fundamental problem in software development is complexity. • Divide and Conquer • Share and build upon commonalities • Base classes, inheritance • Templates • Create well-defined interfaces between logical components • Class protection • Consider evolution in design: no program is written once and then left untouched
Optimizing Program Performance • Use better algorithms. • Quick sort is much better than bubble sort. • FFT is an example of “divide and conquer” • A hash table offers constant access time. • Use better Programming techniques. • Parallel Processing .
Optimizing Program Performance • Inline assembly code (gcc only): __asm__(code string [: output[ : input [ : overwrite]]]); for (j = 0; j < N; j += 4) { __asm__ ("movaps %1, %%xmm0 \n\t" \ "movntps %%xmm0, %0" \ : "=m" (c[j]) : "m" (a[j])); } SSE Instructions for P3, P4 8 128 bit floating registers for (j = 0; j < N; j++) c[j] = a[j];
Optimizing Program Performance • Use optimizing flags of your compiler. • -O flag • int foo1 (int* xp, int* yp) {*xp += *yp; *xp += *yp;} • int foo2 (int* xp, int* yp) { *xp += 2* *yp;} • Eliminating Loop Inefficiencies • for (k = 0; k < n; k += 2) { c[k] = a[k] + b[k]; c[k + 1] = a[k + 1] + b[k + 1]; }
Optimizing Program Performance • Reducing Procedure (Function) Calls. • Stack and saving registers overhead. • Use inline functions or macros. • Reducing Unneeded Memory References. void add (int* array, int* res) { *res = 0; for (int k = 0; k < n; k++) *res = *res + array[k]; } void add (int* array, int* res) { int x = 0; for (int k = 0; k < n; k++) x = x+ array[k]; *res = x; }