Transcript Introduction to C++ - University of Central Florida
An Introduction to C++
COP 4331: OO Processes for Software Development © Dr. David A. Workman School of EE and Computer Science University of Central Florida January 19, 2007 September 3, 2008
The UNIX C++ Environment
Getting Started
Your C++ Working Directory C++ Source Files
Header-files .h
Source-files .cpp
g++ Compiler C++ Object Files (.o) .h files contain module interfaces .
cpp files contain module implementation details The program entry point is the main() function that must be defined in a .cpp
file.
September 3, 2008
> g++ -c filename.cpp
One or more compilation-only steps.
Each successful compilation produces a .o
file. Only .cpp
files are compiled.
.h
files will be compiled when a #include statement is processed.
> g++ -c filename.cpp >& filename.msg
This illustrates how to redirect
stderr
to a file to save compilation messages.
(Note: In C++ the standard files are: cin, cout, cerr) > g++ mainfile.o file1.o file2.o … -o executable-name
Compile the main file, link .o files, and produce an executable.
(c) Dr. David A. Workman 2
C++ Program Organization
Organization Principle: All C++ programs should consist of a (.cpp) file holding the main() function together with a collection of paired header (.h) and implementation (.cpp) files that represent one or more of the following: (a) a Class type (b) an single Object defined by a namespace (c) a namespace encapsulating a collection of Classes and other related C++ entities AppProgram.cpp
Main() ClassA.h
ObjectX.h
Header File Header File IOMgmt.h
Header File ClassA.cpp
ObjectX.cpp
….
IOMgmt.cpp
Implementation File Implementation File Implementation File
September 3, 2008 (c) Dr. David A. Workman 3
C++ Organization (contd)
Alpha.h
Example.cpp
#include "Alpha.h" #include "Beta.h" #include "IOMgmt.h" using namespace IOMgmt; int main() { InMgr finMgr( "Enter name of input file:"); ifstream& fin = finMgr.getStream(); Alpha One; //Class type One.Extract( fin ); //Class operation Beta::Initialize(); //Operation on single object Beta ….
finMgr.close(); return 0; } #ifndef _ALPHA #define _ALPHA //includes go here class Alpha { public: Alpha(); void Extract( ifstream& fin) throw(TokenError ); … private: // declare data members here }; #endif Alpha.cpp
{ } #include "Alpha.h" Alpha::Alpha() //Constructor Class Module { void Alpha::Extract( ifstream& fin) throw(TokenError ) //procedure if( … ) throw TokenError( "Bad Syntax", "Alpha::Extract()"); } …
September 3, 2008 (c) Dr. David A. Workman 4
C++ Organization (contd)
Beta.h
Single Object Module (namespace) Example.cpp
#include "Alpha.h" #include "Beta.h" #include "IOMgmt.h" using namespace IOMgmt; int main() { InMgr finMgr( "Enter name of input file:"); ifstream& fin = finMgr.getStream(); Alpha One; //Class type One.Extract( fin ); //Class operation Beta::Initialize(); //Operation on single object Beta ….
finMgr.close(); return 0; } #ifndef _BETA #define _BETA //includes go here namespace Beta { void Initialize() ; // other function and procedure declarations … } #endif Beta.cpp
#include “Beta.h“ using namespace Beta; // other includes needed by the implementation of Beta namespace Beta { // define private data – visible to rest of namespace Beta void Initialize { //body of procedure Initialize (initializes private data above) } For other examples of Single Object namespaces, see IOMgmt::FileParser & IOMgmt::Concordance } … bodies of other functions and procedures of Beta
5 September 3, 2008 (c) Dr. David A. Workman
C++ Organization (contd)
Namespace Module (see IOMgmt) AppError IOMgmt TokenError OutMgr IOError InMgr Tokenizer StringTokenizer Not used in this course.
September 3, 2008 (c) Dr. David A. Workman 6
Unix Make Utility Program
makefile
make Your C++ Working Directory
September 3, 2008
C++ Source Files (.h, .cpp) C++ Object(.o) Files Executable File (a.out)
(c) Dr. David A. Workman 7
Make Files
See Notes
# makefile for foo_to_v5d.c conversion program (this is a comment) PROGRAM = lab_2 CFLAGS = -c CC = g++ LIBS = -lm OBJECTS =
$(PROGRAM).o file1.o file2.o … filek.o
# introduces comments
identifier =
declarations
$(PROGRAM): $(OBJECTS)
$(CC) $(OBJECTS) $(LIBS) -o
$(PROGRAM) $(PROGRAM).
o:
$(PROGRAM).
cpp $(CC) $(CFLAGS) $(PROGRAM).cpp >& $(PROGRAM).err
file1
.o:
file1
.cpp
file1.
h $(CC) $(CFLAGS) ...
file1
.cpp
filek
.o:
filek
.cpp
filek.
h $(CC) $(CFLAGS)
filek
.cpp
Identifier : introduces a rule
File0: File1 File2 … Filek command
To "run" a makefile : > make
or
> make -f
makefile-name
September 3, 2008 (c) Dr. David A. Workman 8
September 3, 2008
Makefile Example
apperror.cpp
iomgmt.cpp
simmgmt.cpp
simmodels.cpp
includes apperror.h
Includes includes includes iomgmt.h
Includes simmgmt.h
Includes includes simmodels.h
Includes simapp.cpp
Compilation Dependency Graph
(c) Dr. David A. Workman 9
executable
Makefile Example
Link in Math library Name of the executable simapp: simapp.o simmodels.o simmgmt.o iomgmt.o apperror.o
g++ -l m -o simapp simapp.o simmodels.o simmgmt.o iomgmt.o apperror.o
apperrors.o: apperror.cpp apperror.h
g++ -c apperror.cpp
Names of object files needed to create executable iomgmt.o: iomgmt.cpp iomgmt.h apperror.h
g++ -c iomgmt.cpp
simmgmt.o: simmgmt.cpp simmgmt.h iomgmt.h apperror.h
g++ -c simmgmt.cpp
simmodels.o: simmodels.cpp simmodels.h simmgmt.h iomgmt.h apperror.h
g++ -c simmodels.cpp
simapp.o: simapp.cpp simmodels.h simmgmt.h iomgmt.h apperror.h
g++ -c simapp.cpp
September 3, 2008 (c) Dr. David A. Workman 10
C++ Example
See Notes info1.cpp
#include #include #include
// format manipulator operations with parms // string class using namespace std
;
// using directive for standard C++ namespace void
Get_Text( string& Data );
// global function declaration int main() {
// This program prompts the user for: name, phone, and address.
// variable and object declarations:
const char
Blank = ' ';
string
Blank_Line(25,Blank); // initial string of 25 blank chars
string
Name; // initialized to the null string
string
Phone; // initialized to the null string
string
Address[3]; // array of 3 string objects // Executable statements
… see next slide return 0;
// OK, no errors
} void Get_Text( string& Data ) { // function definition // string& is the "pass by reference" operator cin >> Data; // Extraction for string expects a sequence of non-wsp chars }
September 3, 2008 (c) Dr. David A. Workman 11
C++ Example (continued)
// Prompt for user's name.
cout
<< "Enter your name: "; // Insertion operator << Get_Text( Name); // cin >> Name;
// Prompt for user's phone.
cout
<< "Enter your phone # (aaa)xxx-xxxx: "; Get_Text(Phone); // cin >> Phone;
// Prompt for user's address.
cout
<< "Enter each of three address lines.") <<
endl
;
cout
<< "Press ENTER for blank lines." <<
endl
;
for( int // Always end your programs with a EOL to clear the system output buffer // before returning to the OS.
cout
i = 0; i < 3; i++) Get_Text(Address[i]); << '\n'; // cout << endl; // cin >> Address[i]; September 3, 2008 (c) Dr. David A. Workman 12
• • • • • •
Summary of Features
CLASSES
Classes are defined in C++ using two encapsulation features: class and struct . Classes and Structs define a new type. Classes and Structs differ in the visibility rules to "member" data and function declarations . Class and Struct declarations should be placed in header files (.h).
Member function and data definitions are placed in a corresponding source file (.cpp).
FILE IO
C++ supports stream IO on external files. You must #include
EXCEPTIONS
Exceptions are special classes used for error handling at runtime. An exception is an instance of some class created by a throw statement. A “throw” interrupts the normal flow of control and transmits the exception instance up the call chain until a catch block is encountered that will handle the exception type. (Exceptions in C++ are very similar to Exceptions in Java)
NAME SPACES
Name spaces are like package declarations in Ada and in Java. They create a named frame for encapsulating related types, data, functions, classes, and even nested namespaces. Names declared in a name space are accessed using the scope resolution operator (::), unless a using declarative is given.
SCOPE and VISIBILITY RULES TEMPLATES
Template classes in C++ are similar to generic packages in Ada. C++ also supports template functions , which are similar to generic subprograms in Ada.
September 3, 2008 (c) Dr. David A. Workman 13
Types, Values and Objects in C++
•
Primitive C++ types
– –
char, int, float, double, void // C types bool, wchar_t // new primitive types (Boolean, wide character) bool is an integer type with two predefined values (false = 0, true = 1) wchar_t is a 16-bit character type used to represent the international char. set
•
Composite C++ types
– –
struct, union, enum // C structured types - different properties in C++ class // C++ encapsulated type Example. In C struct t { int x; float y;}; // type is (struct t) struct t A; A.x = 5; // variable of type (struct t) // component reference
C++ unions and enums are similar to structs and classes
Example. In C++ struct t { int x; float y;}; t A; // “struct” no longer required A.x = 5;
September 3, 2008 (c) Dr. David A. Workman 14
Pointers and References Definitions
–
A pointer is a value that denotes a program location. A pointer variable is a variable that holds pointer values. The type associated with a pointer variable or value constrains the kind of object or variable at the designated location.
–
A reference is a name designating a program location.
Examples
int x, y; int *p = &x; // p is a pointer variable that can hold the location of integer variables int &q = y; // q is a reference constant that can hold the name of integer variables.
// q and y are now names of the same variable.
// references must always be initialized and cannot change thereafter!!!
int *f() { return &x; } // result is a pointer value designating the location of x int &g(){ return x; } // result is a reference value denoting an alias for x.
void swap( int *a, int *b){ int t = *a; *a = *b; *b = t; } //call: swap(&x, &y); void swap( int &a, int &b){ int t = a; a = b; b = t; } //call: swap(x, y); // swap( x, y ) is the same as swap( x, q) using the last defintion of swap().
g() = y+2; // Valid?? If so, what does it do?
September 3, 2008 (c) Dr. David A. Workman 15
#include
File IO
int main() { // file object declarations ifstream fin; // ifstream is a subclass of fstream for input streams fin.open("income.dat“, ios::in); // external file name specified in open method ofstream fout; // ofstream is a subclass of fstream for output streams fout.open("tax.out“: ios::out); int income; float tax; // declarations are compiled and have their effect as encountered while ( fin >> income ){ // equates to "true" until EOF is encountered (fin != 0) if( income < ::cutoff ) // :: cutoff refers to the global name “cutoff” tax = ::rate1*income; // implicit type conversion between int and float else tax = ::rate2*income; fout << "Income = " << income << " Drachma \n" << " Tax: " << (int) tax*100.0 << " Lepta" << endl; See Notes } }//while fin.close(); // close file objects fout.close(); return 0;
September 3, 2008 (c) Dr. David A. Workman 16
#include
File IO
#include
September 3, 2008 (c) Dr. David A. Workman
See Notes
17
Classes Definition class
typename
{ [
private data and function members // default visibility access-specifier : data and function members
]+
See Notes Page
} [
– –
object-list
] ;
A class introduces a new encapsulated type, members
• • • •
private public = visible only to the
class methods
protected = visible anywhere the class is visible .
Default access
typename . Access-specifier determines visibility of declared data and function
and
friend functions
= visible to methods of any subclass (derived class) is private , or the value of the most recent access-specifier.
–
Data members: act like C struct components; object attributes and state variables. The encapsulated data associated with each class instance is the collection of all declared data members, regardless of their individual visibility properties. A distinct copy of all (non-static) data members are allocated and initialized each and every time a class constructor is called.
–
Member methods : define operations on class instances. They hide the details of implementation of class instances and manage instance data.
September 3, 2008 (c) Dr. David A. Workman 18
Classes Semantic Rules
1. Class constructors perform two function in this order:
a) Allocate each (non-static) data member in the order declared.
b) Initialize each data member in the order declared. Primitive types are initialized implicitly to their default value, or explicitly from constructor parameters. Composite data members are initialized implicitly by calling the default constructor for the appropriate class or struct, or explicitly by calling a parameterized constructor. Arrays are treated as composite types and the array elements are initialized in a manner determined by the element type – as described above.
c) The constructor body is executed.
2. Explicit Initialization (Constructors)
a) Constructor( [
parameters
] ):
data-member
(
expression
), … { … } : Initialization List between colon and { b) Required to initialize (non-static) const class type.
data members or data members of some
3. Class destructors perform two functions in the following order:
a) The body of the destructor is executed.
b) The class destructor (if defined) is called for each (non-static) composite data member in the reverse order of their declarations.
c) The storage allocated to all (non-static) data members is de-allocated in the runtime stack.
September 3, 2008 (c) Dr. David A. Workman 19
Class Definition Example
“Person.h” See Notes Page #include
(1) (2)
(3) (4)
A class declaration
should be defined in a header file.
A constructor
and
destructor
methods have the same name as the class and MUST NOT have declared type; destructors should be declared
virtual
to force redefinition in subclasses.
A
const
method cannot change data members unless they have been declared mutable .
If the body of the method is given in the class declaration (interface), the method is to be
expanded in-line
by the compiler wherever it is referenced AND must not also be defined in the implementation file (.cpp file)!
September 3, 2008 (c) Dr. David A. Workman 20
Class Implementation Example
“Person.cpp” Constructor requires two parameters.
#include
Default constructor NOT defined.
using namespace std; #include "Person.h" Person::Person( string s, int a ) {
// public constructor (creates instances)
name = s; age = a; Destructor is the “default”. It simply } salary = 0.0; Person::~Person() } { See Notes
// public destructor (reclaims instance memory)
deallocates instance memory AFTER calling the destructors for any data members that are instances of other classes (e.g. name ) void Person::GetOlder() {
// public mutator
age += 1; } void Person::GetRaise( float amount ) salary += amount; {
// public mutator
} Mutators change instance attributes.
References to data members are components of the instance to which the method is called.
September 3, 2008 (c) Dr. David A. Workman 21
Class Client
#include
September 3, 2008 (c) Dr. David A. Workman 22
Class Design Principles
1. Only methods should be public .
2. Data members should always be private . Public inspector (read only) methods should be defined to return their value.
3. A default constructor and destructor should always be declared public; the destructor should be declared virtual to force subclasses to redefine them.
4. Destructor methods can default unless the class has data members that are pointers to dynamically allocated memory – this memory must be explicitly de-allocated in the destructor method for the class.
5. A class should have a parametric constructor that enables the definition of all data members.
6. A class should have a parametric constructor and/or an Extract() method that extracts an instance from an external data source (e.g. file stream), if dictated by requirements; a separate constructor and/or overloaded Extract() method should be provided for each different type of external input data source.
7. A class should have an Insert() method that outputs an instance to an external data sink (e.g. file stream); Insert() should be overloaded for each type of external data sink dictated by requirments. 8. The class should be designed to ensure that either an instance of the class cannot be constructed, or, alternatively, cannot be operated on by any other method unless all data members have consistent values that satisfy design constraints for the class. An exception should be thrown by any method that finds the instance state to be incompatible or in violation of class design constraints.
9. A class should be documented with comments , either in the class header file or the class implementation file, stating all design constraints on class data members.
10. A class should NOT define so called "setter" methods that allow clients to directly change the value of a data member. If this rule is violated, then such methods should at least validate design constraints and throw an exception if the constraints are violated by the new value of the data members.
11. "Constant" instances of a class should never be made public as immutable class instances. Instead they should be represented by parameterless functions that return the desired constant instance (value). e.g. Complex Zero(); //Returns the complex value (0.0, 0.0).
Complex ReUnit(); //Returns the complex value (1.0, 0.0) Double Pi(); //Returns the value of PI as a double precision floating point value.
Exceptions Basic Facts
–
Exceptions are objects , that is, instances of exception classes or primitive types. They are created dynamically and automatically by C++ when erroneous primitive operations are attempted (e.g. division by zero), and they can be created by a program throw block when erroneous conditions arise that the program can detect.
–
Exception objects contain data that explain or may be helpful in diagnosing the cause of the erroneous condition. Usually this data is a message identifying the point where the exception occurred and, if possible, why it may have occurred.
–
An exception handler is an action taken by the program invoked in response to an anticipated exception. Exception handlers are defined by catch blocks and are only executed when an exception of the appropriate type is raised within its scope of influence.
–
Exception handlers are bound to code segments that may throw exceptions they can accept via a try block .
– –
Unhandled exceptions propagate up the dynamic call chain and result in abnormal program termination.
C++ automatically performs certain “clean up” operations when exceptions go unhandled as they propagate up the dynamic call chain.
September 3, 2008 (c) Dr. David A. Workman 24
1.
2.
3.
Exceptions: Design Principles
Exceptions should never be caught (handled) in the same method or function that throws them – they should be handled by some active method or function earlier in the call chain at the time the exception is detected.
Exceptions should be caught at every opportunity in the call chain. The "exception message" and "exception origin" information should be updated (appropriately) to allow traceability and to give users and developers the most information possible about the cause of the exception and the conditions exiting at the time the exception occurs.
An exception should be propagated up the call chain to some method (or methods) having the most information to decide how the exception should be handled (recovery or termination).
September 3, 2008 (c) Dr. David A. Workman 25
Example: Exceptions
Stack.h
#include “AppError.h” class Stack{ // stack of integers int topidx; int *contents; public: Stack(); // constructor ~Stack(); // destructor needed void push( int x) throw(AppError) ; int pop() throw(AppError) ; bool empty(); // throws stack overflow and // stack underflow exceptions Header file name should NOT be different from class name.
} Stack.cpp
#include “Stack.h” Stack::Stack(){ // constructor contents = new int[10]; topidx = -1; } Stack::~Stack(){ // destructor needed delete [] contents; } Exception of type AppError void Stack::push( int x) throw(AppError) { if ( topidx >= 9 ) throw AppError("Stack Overflow") ; contents[++topidx] = x; } Throw clauses must agree in header and implementation files Each class is always responsible for checking for erroneous conditions and throwing exceptions when they occur.
} int Stack::pop() throw(AppError) { if (topidx < 0 ) throw (char *) “ Stack Underflow” ; return contents[topidx--]; Exception of type (char *) bool Stack::empty(){ return topidx < 0; }
September 3, 2008 (c) Dr. David A. Workman 26
Example: Exceptions
#include
catch (…){ // handles any exception cout << “Unknown Exception!” << endl; return 1; } //The default handler should always //be placed last among handlers }//for return 0; }// main
September 3, 2008 (c) Dr. David A. Workman 27
Name Spaces
Definition
A namespace is an encapsulation unit used to group declarations and definitions with a common scope. Namespaces can encapsulate the following kinds of declarations:
–
Constant and variable declarations
– –
Struct, union, and class declarations Function prototypes
– –
Function definitions Nested namespaces.
There are three kinds of namespaces:
–
Global namespace : an anonymous namespace composed of all non-static external declarations that do not belong to any other named or unnamed namespace. Select visibility is enabled via the anonymous scope resolution operator (::identifier).
–
Translation unit namespaces : unnamed namespaces defined within a file; they limit the scope of external declarations to the given file; each file defines a unique TU namespace (if declared); TU namespaces obviate the need for global static declarations; declarations in TU namespaces and global declarations are indistinguishable within the same file – only global declarations can have visibility outside the file in which they are defined. Select visibility is enabled via the anonymous scope resolution operator (::).
–
Named namespaces: have an associated identifier that must be unique among all named namespaces. Select visibility is enabled via the scope resolution operator (namespace id::identifier).
September 3, 2008 (c) Dr. David A. Workman 28
Namespaces USES
1. To organize a group of modules for independent and parallel develop by different teams (or individuals). By limiting the scope of names to the namespace, naming conflicts can be avoided when independently developed namespaces are integrated after development.
2. To organize a group of related classes that have a common purpose in the design. For example, subsystems may be encapsulated by namespaces.
3. To implement one-of-a-kind objects (efficiently) without having to create the extra overhead associated with defining classes and restricting the number of instances that can be created.
September 3, 2008 (c) Dr. David A. Workman 29
Name Spaces
Global Namespace See Notes Translation Unit Namespace (one per file) Translation Unit Namespace (one per file) … Translation Unit Namespace (one per file) Named Namespace Named Namespace … Named Namespace
September 3, 2008 (c) Dr. David A. Workman 30
One file
Named namespaces
namespace alpha { int One; typedef int *INTPTR; INTPTR copyint( int value ) { One = value; INTPTR p = new int(One); return p; }//copyint
The namespace “alpha” is directly visible – it is declared in the global namespace.
}//alpha } int main() { alpha::INTPTR p; int x = 25; p = alpha::copyint(x);
Names defined within alpha must be referenced using the scope resolution operator (::), since they are not directly (globally) visible.
September 3, 2008 (c) Dr. David A. Workman 31
Named namespaces
Three files NOTE: The 3-file approach is preferred.
alpha.h
#ifndef ALPHA #define ALPHA namespace alpha { extern int One; //data declaration typedef int *INTPTR; INTPTR copyint( int value ); //fn decl.
}//alpha #endif #include "alpha.h" int main() { alpha::INTPTR p,q; int x = 25; p = alpha::copyint(x); } q = alpha::copyint(alpha::One);
September 3, 2008
#include “alpha.h” namespace alpha { int One; //data definition typedef int *INTPTR;
alpha.cpp
INTPTR copyint( int value ) { //fn defn One = value; INTPTR p = new int(One); return p; }//copyint }//alpha
(c) Dr. David A. Workman 32
Namespace Extension
File1.cpp
#include
void f( float ); // global fn prototype; } int main() { alpha::INTPTR p; int x = 25; p = alpha::copyint(x); cout << “p = “ << *p << endl; cout << “alpha::One = “ << alpha::One << endl; f( float(x)); // type conversion
File2.cpp
#include
An extension to alpha File2.cpp
File2.cpp
{ namespace alpha typedef float *FLTPTR; float Two = 0.0; FLTPTR copyflt( float value ) { //fn defn Two = value; FLTPTR p = new float(Two); return p; }//copyflt }//alpha
See Notes Page
September 3, 2008
//code that uses the local extensions to alpha
(c) Dr. David A. Workman 33
Alpha.h
Namespace Extension
#ifndef ALPHA #define ALPHA { namespace alpha extern int One; //data declaration typedef int *INTPTR; INTPTR copyint( int value ); //fn decl.
Any other files that need to reference Information defined in namespace Alpha Only need to include “Alpha.h” to gain use of features contributed by both File1.cpp
and File2.cpp
extern float Two; //data declaration typedef int *FLTPTR; FLTPTR copyflt( float value ); //fn decl.
}//alpha #endif
September 3, 2008 (c) Dr. David A. Workman 34
See Notes Page
TU namespaces
File1.cpp
#include
File2.cpp
double g( double ); // refers to g in file 1 namespace { // visible to h() and h2() const double pi = 3.1415926; double f( double x) { }//f return x * g(x); }//TU namespace int main() { double y = 25.0* pi ; cout << “y^1.5 = “ << f(y) << endl; cout << “y^-0.5 = “ << g(y) << endl; }// main
September 3, 2008
double h2( double y){ return }//h2
(c) Dr. David A. Workman
pi *y*g(y);
This “pi” hides “::pi” and is only visible in File2.
{ double h( double y) return y/f(y); }//h
Refers to the local “pi” not “::pi”
35
Namespace declarations and directives
• •
Using Declarations
A using declaration adds a specific name declared in a namespace to the local frame where the using declaration is specified.
Using Directive
A using directive applies to namespaces as a whole, and simply makes all names declared in the namespace directly visible (without the scope resolution operator).
namespace beta { int X, Y,Z; } int Z; // global Z int main(){ int X = 0; // local X using namespace beta ; //directive X++; // local X Y++; // beta::Y Z++; // error (::Z or beta::Z )?
::Z++; // global Z beta::Z++; // beta Z ...
}
September 3, 2008
namespace beta { int X, Y,Z; } int Z; // global Z int main(){ int X = 0; // local X using beta::X ; //declaration ( error) using beta::Y ; //declaration ( localizes) } using beta::Z ; //declaration ( hides ::Z) X++; // local X Y++; // beta::Y Z++; // beta::Z ...
(c) Dr. David A. Workman 36
September 3, 2008
Namespace Aliases namespace
alias-name
=
namespace-id
;
namespace beta { int X, Y,Z; namespace delta { float X,Y,Z; } } int Z; // global Z namespace D = beta::delta; //alias declarations int main(){ int X = 0; // local X using namespace beta; //directive X++; // local X beta::X++; // X in beta Y++; // beta::Y using D::Z ; //declaration ( hides ::Z and beta::Z) Y++; // beta::Y Z++; // beta::delta::Z D::X++; // beta::delta::X }
(c) Dr. David A. Workman 37
Namespaces (More Rules) Data definitions in namespaces
•
If data definitions are intended to be made public ( bad practice !), they must be declared extern in the header file and then defined in the implementation file.
•
Data definitions of a primitive type can be defined with initializers in the implementation file.
•
Data definitions of a class or struct type whose memory must be allocated at runtime (e.g. dynamic arrays) must be defined as pointer variables and then dynamically allocated and initialized explicitly by a procedure call during execution (you should define a special procedure (or proceduress) that serves as an initializer for the namespace.
September 3, 2008 (c) Dr. David A. Workman 38
}
Namespaces as Single Objects
Object.h
#include “AppError.h” namespace
Object
{ // Declare C++ functions representing methods of the namespace object.
// At least one of these function must always be defined to properly initialize // the object’s environment before any other method can be called. These //
initialization functions
serve the same purpose as constructors of a class // type. The default initialization method is declared below.
void Initialize(); } Object.cpp
#include “Object.h” namespace
Object
{ void Initialize() { } Define encapsulated data members here. Primitive data can be directly initialized. Data members of a Class type may have to be defined as pointers and intialized by the initialization method(s). Special boolean protocol variables may have to be defined to ensure Initialize() method is called before any other methods.
Define the bodies of the functions declared in the header file. The bodies are defined using The same syntax you would use for functions in C, but they have direct visibility to all data members defined at the top of the namespace.
September 3, 2008 (c) Dr. David A. Workman 39
Concordance.h
#ifndef _CONCORD #define _CONCORD #include
Namespaces as Single Objects
Concordance.cpp
#include using std::list; #include "Concordance.h" #include "Entry.h" namespace Concordance { void AddWordRef( Word& Wrd, Reference& Ref); void Output( ostream& fout); } #endif namespace Concordance { { list
September 3, 2008 (c) Dr. David A. Workman 40
Figure 2
#include “Object.h” int main() { ….
Object::Initialize(); // Call Object initialization fn … Object::Function1(…); // Call Object procedure … x = Object::Function2(…); // Call Object function }
September 3, 2008 (c) Dr. David A. Workman 41
Team1
Team Development with Namespaces
SystemX SubA Class One Class Two Main SubB TeamA TeamB
September 3, 2008 (c) Dr. David A. Workman 42
SubA
Team Development with Namespaces
Ted.h
TeamA: Ted Sally Fred Contains all and only the information Ted needs to make public (for other teams and/or other team members) Ted.cpp
#include “SubA.h” using namespace SubA; #include “SubB.h” namespace SubA { //Ted’s Code } SubA.h
Contains all public declarations for namespace SubA. This is used by clients of SubA (other teams) as well as members of Team A.
September 3, 2008 (c) Dr. David A. Workman 43
• •
Subclasses & Inheritance Syntax
class B { // base class definition // declaration of data and function members … }; class S : public B { // S is a public subclass of B (or derived class of B) // declaration of additional data and function members // redefinition of inherited member functions (optional) };
Semantic Rules
– – –
all members of base or super class are inherited by public members the subclass of the base class are public in the subclass private members of base class are NOT visible to subclass ( private data members can be indirectly accessed only via public functions provided in the base class )
–
members in the base class can be shared with (made visible to) its subclasses, by declaring them protected
–
access to inherited members can be made more restrictive (e.g. public to private) by explicitly re-declaring the member in the subclass with a private using declaration for the base class member.
September 3, 2008 (c) Dr. David A. Workman 44
Subclasses & Inheritance Semantic Rules (continued)
1. Constructors for derived classes initialize instances in the following way:
a) Allocate base class data members.
b) Initialize base class data members (implicitly using default base class constructor or explicitly using parameterized base class constructor defined in the initialization list.) c) Allocate derived class data members.
d) Initialize derived class data members explicitly from initialization list or implicitly by default value or default derived class constructor.
e) Execute the body of the derived class constructor.
2. Destructors for the base class and all derived classes should be defined as virtual to ensure that dynamic binding is used for derived classes.
3. Destructor bodies may need to explicitly de-allocate heap storage referenced by pointer data members. (e.g. dynamically created arrays )
September 3, 2008 (c) Dr. David A. Workman 45
Subtypes Definition: Type S is a subtype of T, if every legitimate value of S is also a legitimate value of T ( “is a” relation)
UCFstudent Attributes1 Methods1 IS-A Inheritance CSmajor Attributes1 Attributes2 Attributes and behaviors unique to CSmajors Methods1 Methods2 In UML the “IS-A” relation is meant to model the subtype relation between two classes.
An instance of CSmajor inherits the characteristics (attributes) and behavior (methods) of its superclass UCFstudent . But, in addition, a CSmajor has characteristics (attributes) of its own that make it different from other UCFstudents and may have certain behavior (methods) that are also unique to CSmajors.
All UCFstudents have a pegasus email address and account.
All CSmajors (after taking COP 4232) have written at least one discrete event simulation. Every CSmajor can do anything a UCFstudent can do (although they probably wouldn’t want to), but there are things a CSmajor can do that a UCFstudent cannot do (e.g., write good C++ code) Reference:
Object-Oriented Software Development Using Java, 2
ISBN = 0-201-73733-7
nd Ed
., by Xiaoping Jia, Addison-Wesley,
September 3, 2008 (c) Dr. David A. Workman 46
Overriding vs Overloading Methods Definition: Overriding
Refers to the definition of an instance method in a subclass that has the same name, signature, and return type as a method in the superclass when the type of the superclass is substituted for the type of the subclass.
EXAMPLE class Shape { private: public: stl::list
September 3, 2008 (c) Dr. David A. Workman 47
Subtype Principles and Concepts Definition: Substitutability of subtypes.
An instance of a subtype cam appear wherever an instance of its supertype can appear or is expected. An instance of a subtype can always substitute for an instance of its supertype .
Definition: Conversion of class types is governed by the subtype relationship.
Conversion from a class subtype to one of its supertypes is called “ widening ” or “ upcasting ”. Conversion from a supertype to one of its subtypes is called “ narrowing ” or “ downcasting ”. Widening is always allowed and is carried out implicitly by the compiler.
Narrowing is allowed at compile-time, but may not be safe and may cause exception at run-time .
Conversion between class types is different from conversion between primitive types: primitive type conversion may result in changing the underlying representation of values (e.g. int to double ), but in class type conversion, the value of the object does not change – only the methods that are called to manipulate it change.
Reference:
Object-Oriented Software Development Using Java, 2 nd Ed
., by Xiaoping Jia, Addison-Wesley, ISBN = 0-201-73733-7
September 3, 2008 (c) Dr. David A. Workman 48
};
Example: Subclasses & Inheritance
class Food { public : Food() { cost = price = 0.0; } //in-line default constructor Food( float c, float p) { cost = c; price = p; } // Parametric constructor float CostIs() const { return cost; } //in-line inspector float PriceIs() const { return price; } //in-line inspector float Margin() const { return price/cost; } //in-line property private : float cost, price; //bad practice //see Note(1) See Notes class Drink : public Food { public : enum { small = 0, medium = 1, large = 2 }; // see Note(2) Drink( int s) { size = s; } // see Note (3) Drink( float c, float p, int s) : Food(c, p) { size = s; } // see Note(4) int SizeIs() const { return size; } float CostIs() const { // see Note(5) return ( size > small )?Food::CostIs()*1.5 : Food::CostIs(); } private : int size; using Food::Margin; //see Note(6) };
September 3, 2008 (c) Dr. David A. Workman 49
Example(continued)
(a) Allocate inherited data (cost, price) (b) Initialize inherited data by default constructor, Food::Food() (c) Allocate Drink data (size) (d) Initialize Drink data: body of constructor class Drink : public Food { public : (a) Allocate inherited data (cost, price) enum { small = 0, medium = 1, large = 2 }; Drink( int s) { size = s; } (c) Allocate Drink data (size) (d) Initialize Drink data (size): contructor initialization list // Drink( int s) : size(s){} Drink( float c, float p, int s) : Food(c, p) { size = s; } a) Allocate inherited data (cost, price) (b) Initialize inherited data by parametric constructor, Food::Food(float c, float p) (c) Allocate Drink data (size) (d) Initialize Drink data: body of constructor // Drink( float c, float p, int s) : Food(c, p), size(s) {} a) Allocate inherited data (cost, price) (b) Initialize inherited data by parametric constructor, Food::Food(float c, float p) (c) Allocate Drink data (size) (d) Initialize Drink data: constructor initialization list
September 3, 2008 (c) Dr. David A. Workman 50
Inheritance & Visibility
Class Subclass: modifier Baseclass {} Access modifier of Base class members Base class member Access specifier Public Members can be accessed by any non static member functions, friends, and other non member functions Protected Members can be accessed by any non static member functions and friends.
Private Members can be accessed by any non static member functions and by friends via protected and public member functions. To other Functions only by Public methods.
Public inheritance Members are public In the derived class. Inherited members of Baseclass are public in the Subclass Inherited members of in the Subclass ( and hidden from Subclass clients).
class. Baseclass are hidden from the Subclass ( and hidden from Subclass clients).
Protected inheritance Members are protected Baseclass are protected in the Subclass ( and hidden from Subclass clients).
Inherited members of in the Subclass ( and hidden from Subclass clients).
Hidden from derived Inherited members of class. Baseclass are hidden from the Subclass ( and hidden from Subclass clients).
Private inheritance Members are private Baseclass are hidden from the Subclass ( and hidden from Subclass clients).
from the Subclass ( and hidden from Subclass clients).
class. Baseclass are hidden from the Subclass ( and hidden from Subclass clients).
September 3, 2008 (c) Dr. David A. Workman 51
• •
Abstract vs. Concrete Classes
Abstract Classes See Notes
Are Classes for which instances can NOT be created.
A C++ class (derived class) is abstract if and only if it declares at least one pure virtual method !
Virtual Methods ( methods that will be redefined in subclasses for which dynamic binding is to be applied)
A method in the base class is declared virtual by using the following syntax:
virtual
A method is pure virtual if the following syntax is used
virtual
The “virtual” attribute is inherited when a method is redefined in a subclass.
Examples
BaseClass *p; //Static type of p is BaseClass SubClass *q; // Static type of q is SubClass p = new Subclass(); //Dynamic type of p is SubClass p->virtualmethod(); // dynamic binding is used; SubClass:: virtualmethod() is called p->ordinarymethod(); // static binding is used; BaseClass::ordinarymethod() is called, even if it is // redefined in SubClass;
September 3, 2008 (c) Dr. David A. Workman 52
Static vs. Dynamic Types
The capability to define object classes, and more importantly, inheritance hierarchies introduces new programming concepts, specifically: (1) a distinction between
static
and
dynamic types
, and (2)
polymorphism
and
runtime binding
.
See Notes!
Shape
*X;
Circle
*A ;
Quadralateral
*Q;
Rhombus
*R;
Parallelogram
*P;
Static types are declared (at compile time )and are associated with variables.
is-a
Class
Shape
(Output )
is-a if ( … )
Q =
new
Rhombus();
else
Q =
new
Parallelogram(); Q->Output();
if ( … )
X =
new
Circle();
else
X =
new
Quadralateral(); X->Output();
is-a
Class
Quadralateral
(Output) Class
Rhombus
(Output)
Dynamic types are defined at runtime and are associated with values (objects).
September 3, 2008 (c) Dr. David A. Workman Class
is-a
(Output) Class
Parallelogram Circle
(Output) 53
Polymorphism and Runtime Binding
See notes
POLYMORPHISM with DYAMIC BINDING
Polymorphism refers to operations that have multiple overriding definitions , depending on the type of object they are applied to. It is a concept very close to that of overloading . However, overriding occurs between methods in different classes related through inheritance, while overloading occurs between methods in the same class. Given a context in which polymorphism applies, two issues arise:
•
How to uniquely determine what definition to bind to the operation name in a given context, and
Class
Shape
(Output ) •
When to bind
a polymorphic name to a definition (compile time or runtime).
is-a is-a PROBLEM: Given the expression Output(X) , which definition of Output do we use?
Class
Quadralateral
(Output) Class
Circle
(Output)
is-a is-a ANSWER: the definition associated with the dynamic type of X. This is runtime binding!
Class
Rhombus
(Output) Class
Parallelogram
(Output) September 3, 2008 (c) Dr. David A. Workman 54
C++ Rules for Runtime Binding For the mechanism of runtime binding to apply when resolving a polymorphic method call, two conditions must be met: 1. The method must be virtual (the virtual property is inherited), and 2. The call must be made using either a pointer or a reference whose static type is a class in which the method is virtual; this class does not need be a base class.
If both of these conditions are met, then a polymorphic reference is resolved by the dynamic type of the object referenced; otherwise the static type of object pointer or reference is used to resolve the method.
September 3, 2008 (c) Dr. David A. Workman 55
Polymorphic Assignment Rule of Assignment:
the type of expression on the right-hand side of an assignment must be a subtype of
EXAMPLE
the type of the variable on the left side.
Shape
*
X, *Y; Circle
*
C ; Rhombus
*
R; X = new Quadralateral(); //OK – rule of assignment Y = new Rhombus(); //OK – rule of assignment R = Y; // Compilation error (declared type of Y // violates rule of assignment.) R = (Rhombus *) Y; // OK – explicit downcast // The compiler will generate code to check the // dynamic type of Y at runtime to ensure it // agrees with the compile-time declaration.
// If the runtime check fails, an exception // is thrown.
R = (Rhombus *) X; // Compiles OK, throws a runtime exception is-a
Class Class
Rhombus
(Output)
is-a
(Output) Class Class
Quadralateral is-a
(Output)
Shape
(Output )
Parallelogram is-a
Class
Circle
(Output) September 3, 2008 (c) Dr. David A. Workman 56
Runtime Binding of Polymorphic Methods
Pet.h
class Pet { public: Pet( string Name, string DNA, char Sex); virtual Output( ostream& fout ); protected: virtual Put( ostream& fout); private: string name; string dna; char sex; }; Cat.h
class Cat : public public: Pet { Cat( string Name, string DNA, char Sex, string Color, int Age); Output( ostream& fout ); protected: Put( ostream& fout); private: string color; int age; }; #include
September 3, 2008 (c) Dr. David A. Workman 57
Pet.h
C++ Example: Class Pet
Pet.cpp
#include "Pet.h" #ifndef _PET #define _PET #include
September 3, 2008 (c) Dr. David A. Workman 58
Cat.h
C++ Example: Class Cat
Cat.cpp
#include "Cat.h" #ifndef _CAT #define _CAT #include "Pet.h" class Cat: public Pet { public: Cat( string Name, string Dna, char Sex, string Color, int Age ); //Constructor virtual void Output( ostream& fout ); protected: virtual void Put( ostream& fout ); private: string color; int age; };//Cat #endif Cat::Cat( string Name, string Dna, char Sex, string Color, int Age ) : Pet(Name, Dna, Sex), color(Color) { //Constructor age = Age; } //Pet void Cat::Output( ostream& fout ) { fout << "Cat{ "; Put( fout ); fout << "}Cat " << endl; }//Output void Cat::Put( ostream& fout ) { Pet::Put(fout); fout << " color: " << color << endl; fout << " age: " << age << endl; }//Put
September 3, 2008 (c) Dr. David A. Workman 59
C++ Example: Pet Application
PetApp.cpp
#include
Pet{ name: Harold dna: Dog sex: Male }Pet Cat{ name: Calvin dna: Cat sex: Male color: White age: 5 }Cat Cat{ name: Calvin dna: Cat sex: Male color: White age: 5 }Cat
September 3, 2008 (c) Dr. David A. Workman 60
Static Class Members Static data members
static
[
const | volatile
]
type data_member ;
– – – –
Shared by all class instances One instance allocated in static data area and initialized at load time, or prior to execution of main().
MUST NOT be initialized by a constructor or modified by a destructor; these methods manipulate non-static data members.
MUST be initialized ONE TIME in (.cpp)(class implementation) file as follows
[ const | volatile ] type class_name ::data_member = initialization_expression ;
September 3, 2008 (c) Dr. David A. Workman 61
Static Class Members Static methods:
static type method( …) ;
– – –
Allow access to static data members!
Do not have a this pointer; cannot access non-static data members!
Called by the statement: classname :: method( ...);
– – – –
Can be called via class instances like other methods.
Can be public, protected, or private.
Can be in-line.
Cannot be const or volatile .
September 3, 2008 (c) Dr. David A. Workman 62
Storage Class Attributes Definitions
Storage class attributes are qualifiers on data (and methods) that determine where the data will be allocated, when and how it will be initialized and destroyed, and what its lifetime will be relative to the program.
–
extern : gives the client access to names defined in the global namespace; the scope of an extern declaration is determined by frame in which it occurs. Data in the global namespace are allocated in the static data area and initialized during execution prior to activation of main(). Their life time is the same as the program life time.
–
static : static global data is allocated in the static data area dedicated to transaction units and is initialized the same as global data. The difference is that static external data can only be accessed by functions and methods that have visibility into the transaction namespace. Static local data is allocated in the appropriate transaction namespace, but is not initialized until the frame that defines it is first activated. The data is accessible only while control is in that defining frame.
September 3, 2008 (c) Dr. David A. Workman 63
Storage Class Attributes Definitions(continued)
–
auto : this is the default storage class. Data in this category is allocated (and possibly initialized) in the runtime stack whenever the defining frame is activated. Such data is destroyed whenever control causes the defining frame to be terminated.
–
mutable : this category is reserved for data members that must be changed by inspector methods (const methods) of a class.
September 3, 2008 (c) Dr. David A. Workman 64
Runtime Memory Organization
Static Data Area (Literals)(Global data) (TU namespaces) (static data members of classes) Runtime stack (function & method parameters & local data) Code Segment (main) (Global Functions) (Class Bodies) Free Space Runtime heap (new)
September 3, 2008 (c) Dr. David A. Workman 65
Constructors Semantic Rules
purpose:
–
to initialize data members when a class instance is created Same name as class.
– –
No return type designation!
Multiple definitions are permitted so long as their signatures are unique
• •
default constructor has no parameters parameterized constructors must differ in order, number, or types of parameters
–
Automatically invoked by a class variable declaration or by the Object declarations create instances in the runtime stack; new in the heap.
new allocator creates instances
– –
Called for each element of an array of objects.
Constructor Execution Order:
• • •
Base class(es) initialized in declaration order Members initialized in declaration order Body of constructor is executed
Example:
Initializing a dynamic array of objects of class Person.
Person family[] = { Person("Martha",55), Person("George",58),Person("Billy",10), Person("Sally",8); };
September 3, 2008 (c) Dr. David A. Workman 66
Copy Constructors Semantic Rules
Purpose: to ensure correct copy semantics when one object is used to initialize another in the following situations:
•
explicit initialization in a declaration Aclass obj1; // default constructor Aclass obj2(obj1); // copy constructor Aclass obj3 = obj2; // copy constructor
•
an object is passed by value to a function void f( Aclass x ); // pass-by-value parameter void g( Aclass &x); // pass-by reference parameter f(obj1); // copy constructor initializes x using obj1 g(obj1); // copy constructor not called
•
an object is returned by value from a function Aclass p( Aclass x ) { return x;} // return-by-value Aclass& q( Aclass &x) {return x;} // return-by-reference obj2 = p(obj1); // copy constructor used to create a temp object as return value obj2 = q(obj2); // copy constructor not called - no temp object is created
Profile:
Aclass ( const Aclass& obj ) { // body } // "const" ensures initializing object is not changed
When to define:
should be explicitly defined as a public method whenever a data member is a pointer to dynamically allocated memory by non-copy constructors.
September 3, 2008 (c) Dr. David A. Workman 67
Copy Constuctor Example ( Set class )
See Notes #include
class set0 { public: set0(); set0(const set0& obj); // default constructor 8 elements // Copy constructor (used by initialization) explicit set0(int size); ~set0(); int getCap() const { return cap; } void addMem(int x); // alternate constructor, specify set size when /= default size // destructor (used when set objects are destroyed) // In-line Inspector // add a memeber set0 operator=(set0 right); set0 operator-(); set0 operator-(set0 right); set0 operator|(set0 right); set0 operator&(set0 right); // assignment (left = right) // complement // difference // union // intersection bool isMem(int x); // membership check friend ostream& operator<<(ostream &stream, set0 obj); //stream insertion // " { e1 e2 ... en } " blank delimited values enumerated in ascending order.
}; friend istream& operator>>(istream &stream, set0 &obj);
//stream extraction
// same format as output except that elements can be given in any order!
private: int cap; // bound on the number of set elements (largest elt = cap-1) unsigned char *elts; // pointer to array of unsigned chars
;
bit "i" (from the left) = "1" means i is a member
September 3, 2008 (c) Dr. David A. Workman 68
Example ( Set class ) Copy Constructor
#include "set0.h" static unsigned char mask1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static unsigned char mask2[8] = {0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF }; set0::set0(){ //default constructor 8 elements
cap = 8;
elts = new unsigned char[1];
elts[0] = 0x00;
} set0::set0(const set0& obj){ //(deep) Copy constructor cap = obj.getCap();
int k = (cap+7)/8;
elts = new unsigned char[k]; for(int i = 0; i < k; i++) if( obj.isMem(i) ) addMem(i); } set0::~set0(){
//destructor cap = 0;
delete[] elts; }
mask1
and
mask2
are arrays of hexadecimal literals. 'static' limits their visibility to the file in which they are declared.
Note the use of the
new
operator to dynamically allocate an array of [?]
unsigned char
.
new
returns a pointer to this allocation.
Note that the data members of
obj
are not visible, so must call public inspector methods to get values.
Note the use of the
delete []
operator to deallocate an array. The pointer
elts
is set to the null pointer as a result.
September 3, 2008 (c) Dr. David A. Workman 69
Copy Constructor Example ( Set class )
#include "set0.h" static unsigned char mask1[8] =
{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
static unsigned char mask2[8] =
{0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
set0 set0:: operator= (set0 right) { // assignment (left = right)
cap = right.getCap(); //capacity is that of the
right
delete []elts; //destruct array of
left
elts = new unsigned char[cap]; //allocate array same size as
right
for(int i = 0; i < (cap+7)/8; i++)
// make deep copy
if( right.isMem(i) ) addMem(i);
return *this; //required for overloaded assignment operator } ostream& operator<< (ostream &stream, set0 obj) { //stream insertion
int k, x; stream << " { "; for(k = 0; k < obj.cap; k++ ){
//friends have direct visibility to data members
x = obj.elts[k/8] & mask1[k%8]; if( x != 0 ) stream << dec << k << " "; } stream << "} ";
return stream; }
September 3, 2008 (c) Dr. David A. Workman
See Notes
70
Destructors Semantic Rules
–
The compiler generates calls to destructors when declared objects pointers to objects) go out of scope (or declared – control leaves the frame that created them.
– – –
The compiler generates calls to destructors when the delete operator is called.
Needed to free memory allocated by constructors.
Defined in the class declaration by : ~class-name(); // NO ARGUMENTS, NO RETURN TYPE
– – – –
AT MOST ONE destructor may be defined for a class.
Destructors should be declared virtual so they will be redefined in subclasses.
Should have the same access attributes as constructors.
Can be declared in-line .
September 3, 2008 (c) Dr. David A. Workman 71
Standard Template Library (STL)
•
Sequence Containers: linear data structures
vector deque list //rapid insertion and deletion at back; direct access by indexing //rapid insertion and deletion at front and back; direct access by indexing.
//doubly linked; rapid access, insertion, and deletion anywhere (at any position)
•
Associative Containers
set multiset map multimap //rapid lookup; no duplicates //rapid lookup; duplicates allowed //key-based lookup; one-to-one mapping; no duplicates //key-based lookup; one-to-many mapping; duplicates allowed
•
Container Adapters
stack queue //LIFO access //FIFO access priority_queue //HPO access (Highest Priority Out)
September 3, 2008 (c) Dr. David A. Workman 72
Standard Template Library
•
Common member functions for all STL containers
– – – – – – – – – – – –
Default constructor Copy constructor Destructor bool empty() int max_size() operator= operator< operator> operator>= operator== operator!= swap // true if no elements, else false //maximum number of elements allowed //container assignment //binary “less than” for containers //binary “greater than” for containers //binary “greater than or equal” for containers //binary “equal” for containers //binary “not equal” for containers //swaps the elements of two containers
September 3, 2008 (c) Dr. David A. Workman 73
Standard Template Library
• – – – –
Member functions common to all FIRST-CLASS STL containers (FIRST-CLASS containers consist of all Sequential and Associatiave containers)
–
begin // two versions: one returns an iterator , one a const_iterator // iterators are instances of nested classes defined with the container // class; they are used to iterate over all objects held by the container // these iterators start at the “first” object held by the container
–
end rbegin rend // two versions corresponding to begin; these iterators return a // fictitious object just beyond the “last” object held by the container; // “reverse” interators similar to begin // “reverse” iterators similar to end erase clear // erases one or more elements from the container // erases all elements in the container leaving it “empty”.
September 3, 2008 (c) Dr. David A. Workman 74
STL Header Files
•
All STL classes are defined in namespace std . The header files that must be included to gain visibility are listed below.
– – – – – – – –
//contains both
queue
and
priority_queue
//contains both
map
and
multimap
//contains both
set
and
multiset
September 3, 2008 (c) Dr. David A. Workman 75
STL typedefs
•
All first-class containers define a common set of typedefs to make it convenient for programmers to refer to lengthy and complex type names. These can be used to declare variables, parameters and return values from functions.
–
value_type // the type of element stored in a container
– –
reference const_reference // a reference to the type of element stored in a container // a const reference to the type of element stored in a container; it can be used only for read and other const operations on container elements.
– – – –
pointer iterator const_iterator reverse_iterator // a pointer to the type of element stored in a container // an iterator that points to elements stored in a container // a const iterator that points to elements in a container // a reverse iterator that points to elements in a container
– –
const_reverse_iterator difference_type // a const reverse iterator that points to elements in a container // the type of result associated with operator- applied to two containers (not defined for list class and Associative containers)
–
size_type // the type used to count items in a non-list container via indexing operations
September 3, 2008 (c) Dr. David A. Workman 76
STL Iterators
•
Definition: Iterators are objects that enable the programmer to successively
access (iterate over) elements stored in a container object without having to know or use the internal data structures and organization used by the container class.
In C++, iterators are defined as nested classes within their associated container classes. Furthermore, they have exactly the same properties as pointers to container elements.
•
Iterator Applications
– –
Outputting all elements of a container.
Updating all elements of a container, or all elements satisfying a given condition.
– – –
Searching a container for a given element.
Deleting or removing all elements satisfying a given condition.
Sorting the elements in a container.
September 3, 2008 (c) Dr. David A. Workman 77
STL Iterators
• •
Iterator Methods for List Containers
The following methods operate on
list::interator and list::reverse_iterator * (unary dereference operator) gives access to the list element referenced by the iterator.
++ (postfix increment) advances the iterator to the next list element; (closer to end()); when the iterator is at end(), then ++ advances it to begin() -- (postfix decrement) advances the iterator to the previous list element; (closer to begin()); when the iterator is at begin(), -- advances it to end() == (iterator equality) returns true iff two iterators reference the same list element (the elements themselves may not be equal) != (iterator not equal) returns true iff two iterators do not reference the same list element.
Example
std::list
for( intiter = listofint.begin(); intiter < listofint.end(); intiter++ ) if ( *intiter < 0 ) cout << *intiter;
September 3, 2008 (c) Dr. David A. Workman 78
STL list Class
•
The list class defined in the STL is a container class that is parameterized by the type of elements it contains.
For example, its declaration has the following form:
template
•
Example declarations of list objects:
– –
std::list< int > Inlist; // declares a list object called “Inlist” that can hold “int”s.
std::list< Shopper > Shopperlist; // a list of Shopper objects called “Shopperlist”.
September 3, 2008 (c) Dr. David A. Workman 79
STL list Class
• – – – – – – – –
Methods: in all the profiles below, T denotes the element type.
– –
list() //default constructor list(int n, const T& value = T()) //construct (n) elements all initialized to (value); //if (value) is omitted, the default constructor for //type T is called – and therefore must be defined.
T& front( ) // [!empty()] returns value at the front of the list void push_front( T e) // creates a new element at the front of the list with value e T& pop_front( ) T& back( ) void push_back( T e) // creates a new element at the back of the list with value e T& pop_back( ) bool empty( ) int size() // [!empty()] destructs the element at the front of the list // [!empty()] returns value at the back of the list // [!empty()] destructs the element at the back of the list // returns “true” if the list has at least one element // returns the number of elements in the list
September 3, 2008 (c) Dr. David A. Workman 80
•
STL list Class Iterator Methods: in all the profiles below, T denotes the element type.
– – – – – – – –
iterator begin() iterator end() const_iterator begin() //returns a pointer front element of list //returns a const pointer (beyond back) element of list //returns a pointer to (const front) element of list const_iterator end() //returns a const pointer (beyond back) element of list void erase( iterator pos )// [!empty()] destruct the element at (pos) void erase( iterator first, iterator last) // [!empty()] destruct the elements in [first,last).
iterator insert( iterator pos, const T& value ) // create a new element with (value) before (pos) more…
September 3, 2008 (c) Dr. David A. Workman 81
STL Examples Function to output a list with element type, T.
#include using namespace std; void output( const list
September 3, 2008 (c) Dr. David A. Workman 82
STL Examples Function to order a list with element type, T, allowing duplicates
begin() ++ - end()
#include using namespace std; void insert( list
; if ( n == 0 ) { listofT.push_front(value); return; }else{ list
}//output
September 3, 2008 (c) Dr. David A. Workman 83