C++-tour4 - The C Programming Language A Tour Through C...

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: The C++ Programming Language A Tour Through C++ Outline C++ Overview C++ Design Goals Major C++ Enhancements Other Enhancements Language Features Not Part of C++ Function Prototypes C++ Classes Class Vector Example C++ Objects C++ Object-Oriented Features 1 C++ Overview Inheritance Preview Inheritance Example: Ada-style Vectors Dynamic Binding Preview Overloading New-Style Comments Type-Safe Linkage Inline Functions Dynamic Memory Management Const Type Quali er Stream I O Boolean Type References Type Cast Syntax Default Parameters Declaration Statements Abbreviated Type Names User-De ned Conversions Static Initialization Miscellaneous Di erences C++ Design Goals C++ was designed at AT&T Bell Labs by Bjarne Stroustrup in the early 80's The original cfront translated C++ into C for portability  However, this was di cult to debug and potentially ine cient Many native host machine compilers now exist  e.g., Borland, DEC, GNU, HP, IBM, Microsoft, Sun, Symantec, etc. C++ is a mostly upwardly compatible extension of C that provides: 1. Stronger typechecking 2. Support for data abstraction 3. Support for object-oriented programming C++ supports the Object-Oriented paradigm but does not require it 2 As with C, run-time e ciency is important e.g., unlike Ada, complicated run-time libraries have not traditionally been required for C++  Note, that there is no language-speci c support for concurrency, persistence, or distribution in C++ Compatibility with C libraries and UNIX tools is emphasized, e.g., Object code reuse  The storage layout of structures is compatible with C  Support for X-windows, standard ANSI C library, UNIX system calls via extern block C++ works with the make recompilation utility 3 C++ Design Goals cont'd Major C++ Enhancements As close to C as possible, but no closer" 1. C++ supports object-oriented programming features i.e., C++ is not a proper superset of C, so that backwards compatibility is not entirely maintained e.g., single and multiple inheritance, abstract base classes, and virtual functions  Typically not a problem in practice ::: Note, certain C++ design goals con ict with modern techniques for: 1. Compiler optimization e.g., pointers to arbitrary memory locations complicate register allocation and garbage collection 2. Software engineering e.g., separate compilation complicates inlining due to di culty of interprocedural analysis 2. C++ facilitates data abstraction and encapsulation that hides representations behind abstract interfaces e.g., the class mechanism and parameterized types 3. C++ provides enhanced error handling capabilities e.g., exception handling 4. C++ provides a means for identifying an object's type at runtime e.g., Run-Time Type Identi cation RTTI 5 4 Other Enhancements C++ enforces type checking via function prototypes Allows several di erent commenting styles Other Enhancements cont'd References provide call-by-reference" parameter passing Declare constants with the const type quali er Provides type-safe linkage Provides inline function expansion New mutable type quali er Built-in dynamic memory management via new and delete operators New bool boolean type Default values for function parameters New type-secure extensible I O interface called streams and iostreams Operator and function overloading 6 7 Other Enhancements cont'd A new set of function call"-style cast notations Language Features Not Part of C++ Variable declarations may occur anywhere statements may appear within a block 1. Concurrency The name of a struct, class, enum, or union is a type name 2. Persistence See Concurrent C" by Nehrain Gehani See Exodus system and E programming language Allows user-de ned conversion operators Static data initializers may be arbitrary expressions 3. Garbage Collection See papers in USENIX C++ 1994 C++ provides a namespace control mechanism for restricting the scope of classes, functions, and global objects 9 8 Function Prototypes cont'd Function Prototypes C++ supports stronger type checking via function prototypes Unlike ANSI-C, C++ requires prototypes for both function declarations and de nitions Function prototypes eliminate a class of common C errors  e.g., mismatched or misnumbered parameter values and return types Proper prototype use detects erroneous parameter passing at compile-time, e.g., if de ned  STDC  jj de ned  cplusplus extern int freopen const char *nm, const char *tp, FILE *s; extern char *gets char *; extern int perror const char *; else * Original C-style syntax. * extern int freopen , perror ; extern char *gets ; endif * de ned  STDC  * ** int main void f char buf 80 ; ::: Prototypes are used for external declarations in header les, e.g., extern char *strdup const char *s; extern int strcmp const char *s, const char *t; FILE *fopen const char * lename, const char *type; extern void print error msg and die const char *msg; 10 if freopen ". foo", "r", stdin == 0 perror "freopen", exit 1; while gets buf != 0 g * ::: *; 11 Function Prototypes cont'd Overloading The preceeding program fails mysteriously if the actual calls are: Two or more functions or operators may be given the same name provided the type signature for each function is unique: * Extra argument, also out-of-order! * freopen stdin, "new le", 10, 'C'; 1. Unique argument types: double square double; Complex &square Complex &; 2. Unique number of arguments: void move int; void move int, int; * Omitted arguments. * freopen "new le", "r"; A Classic C" compiler would generally not detect erroneous parameter passing at compile time though lint would Note, C++ lint utilities are not widely available, but running GNU g++ -Wall provides similar typechecking facilities Function prototypes are used in both definitions and declarations Note, the function prototypes must be consistent!!! A function's return type is not considered when distinguishing between overloaded instances e.g., the following declarations are ambiguous to the C++ compiler: extern double operator Complex &, Complex &; extern Complex operator Complex &, Complex &; Note, overloading is really just syntactic sugar!" 13 12 C++ Classes The class is the basic protection and data abstraction unit in C++ i.e., rather than per-object" protection The class mechanism facilitates the creation of user-de ned Abstract Data Types ADTs A class declarator de nes a type comprised of data members, as well as method operators C++ Classes cont'd For e ciency and C compatibility reasons, C++ has two type systems 1. One for built-in types, e.g., int, oat, char, double, etc. 2. One for user-de ned types, e.g., classes, structs, unions, enums etc.  Data members may be both built-in and userde ned Note that constructors, overloading, inheritance, and dynamic binding only apply to user-de ned types Classes are cookie cutters" used to de ne objects This minimizes surprises, but is rather cumbersome to document and explain :::  a.k.a. instances 14 15 C++ Classes cont'd C++ Classes cont'd General characteristics of C++ classes: A class is a type constructor" e.g., in contrast to an Ada package or a Modula 2 module  Note, these are not types, they are encapsulation units" Until recently, C++ did not have a higher-level modularization mechanism :: :  This was a problem for large systems, due to lack of library management facilities and visibility controls Recent versions of the ANSI C++ draft standard include mechanisms that addresses namespace control and visibility scoping, e.g.,  Name spaces Any number of class objects may be de ned  i.e., objects, which have identity, state, and behavior Class objects may be dynamically allocated and deallocated Passing class objects, pointers to class objects, and references to class objects as parameters to functions are legal Vectors of class objects may be de ned A class serves a similar purpose to a C struct However, it is extended to allow user-de ned behavior, as well  Nested classes 16 17 Class Vector Example There are several signi cant limitations with built-in C and C++ arrays, e.g., 1. The size must be a compile-time constant, e.g., void foo int i f int a 100 , b 100 ; int c i ; Error! 4 lack of range checking 3. Legal array bounds run from 0 to size , 1 4. No range checking performed at run-time, e.g., a i = 0; g 5. Cannot perform full array assignments, e.g., Error! Later on we'll use inheritance to nish the job, i.e., 2 resizing 3 non-zero lower bounds int a 10 , i; for i = 0; i = 10; i++ a = b; We can write a C++ class to overcome some of these limitations, i.e., 1 compile-time constant size OK g 2. Array size cannot vary at run-time f Class Vector Example cont'd 18 5 array assignment 19 Class Vector Example cont'd * File Vector.h this ADT is incomplete wrt initialization and assignment ! * ::: if !de ned  VECTOR H de ne VECTOR H Class Vector Example cont'd * File Vector.C * Wrapper section typedef int T; class Vector f public: Vector size t len = 100 f this- size = len; this- buf = new T len ; g ~Vector void f delete this- buf ; g size t size void const f return this- size ; g bool set size t i, T item; bool get size t i, T &item const; private: size t size ; T *buf ; bool in range size t i const f return i = 0 && i this- size ; g g; endif * VECTOR H * include "Vector.h" bool Vector::set size t i, T item f if this- in range i f this- buf i = item; return true; g else g return false; bool Vector::get size t i, T &item const f if this- in range i f item = this- buf i ; return true; g else return false; g 21 20 Class Vector Example cont'd Class Vector Example cont'd len File test.C include libc.h include "Vector.h" void foo size t size f Vector user vec size; Call constructor int c vec size ; Error, no dynamic range dynamically allocated memory of size len c vec 0 = 0; user vec.set 0, 0; buf for int i = 1; i user vec.size ; i++ f int t; The control block that represents an object of class Vector g user vec.get i , 1, t; user vec.set i, t + 1; c vec i = c vec i , 1 + 1; Note, the control block may be allocated o the stack, the global data segment, or the heap Error, private and protected data inaccessible size = user vec.size , 1; user vec.buf size = 100; However, the buf eld always points to memory allocated o the heap if user vec.set user vec.size , 1000 == false 22 Run-time error, index out of range err "index out of range"; Index out of range not detected at runtime! c vec size = 1000; g Destructor called when user vec leaves scope 23 Class Vector Example cont'd Class Vector Example cont'd * File Vector.h * Note that this example has several unnecessary limitations that are addressed by additional C++ features, e.g., set get paradigm di script notation ers from C's built-in sub- Error checking via return value is somewhat awkward Only works for a vector of ints Classes that inherit from Vector may not always want the extra overhead of range checking ::: The following example illustrates several more advanced C++ features typedef int T; template class T class Vector f public: struct RANGE ERROR fg; Vector size t len = 100: size len f if this- size = 0 throw Vector T ::RANGE ERROR ; else this- buf = new T this- size ; g ~Vector void f delete this- buf ; g size t size void const f return this- size ; g T &operator size t i f if this- in range i return this- buf i ; else throw Vector T ::RANGE ERROR ; g protected: T &elem size t i f return this- buf i ; g private: Don't worry, we'll cover these features in much greater detail over the course of the class!!!! g; 24 size t size ; T *buf ; bool in range size t i f return i = 0 && i this- size ; g 25 Class Vector Example cont'd File test.C include libc.h include "Vector.h" void foo size t size f try f Illustrates exception handling Vector int user vec size; Call constructor int c vec size ; Error, no dynamic range ::: c vec 0 = user vec 0 = 0; for int i = 1; i user vec.size ; i++ f user vec i = user vec i , 1 + 1; c vec i = c vec i , 1 + 1; g Error, private and protected data inaccessible size = user vec.size , 1; user vec.buf size = 100; user vec.elem 3 = 120; Run-time error, RANGE ERROR thrown user vec user vec.size  = 1000; Index out of range not detected at runtime! c vec size = 1000; g C++ Objects A C++ object is an instance of a class or any other C++ type for that matter  ::: An object can be instantiated or disposed either implicitly or explicitly, depending on its life-time As with C, the life-time of a C++ object is either static, automatic, or dynamic C and C++ refer to this as the storage class" of an object Destructor called when user vec leaves scope catch Vector int ::RANGE ERROR f * * g g ::: 26 27 C++ Objects cont'd C++ Objects cont'd Life-time or storage class:" 1. Static i.e., it lives throughout life-time of process Stack 2. Automatic Automatic Variables Heap High Addresses static can be used for local, global, or classspeci c objects note, their scope is di erent Dynamic Variables Uninitialized Global Data i.e., it lives only during function invocation, on the run-time stack" Initialized Global Data Low Addresses 3. Dynamic Text Static Variables Read-Only Code and Data i.e., it lives between corresponding calls to operators new and delete  Or malloc and free Typical layout of memory objects in the process address space Dynamic objects have life-times that extend beyond their original scope 29 28 C++ Objects cont'd C++ Objects cont'd Several workarounds exist, however, e.g., Use Ei el or LISP ;- Most C++ implementations do not support automatic garbage collection of dynamically allocated objects Use inheritance to derive from base class Collectible  However, this only works then for a subset of classes i.e., doesn't work for built-in types  In garbage collection schemes, the run-time system is responsible for detecting and deallocating unused dynamic memory ::: Note, it is very di cult to implement garbage collection correctly in C++ due to pointers and unions Use the class-speci c new and delete operators to de ne a memory management facility using reference counts to reclaim unused memory Therefore, programmers must explicitly deallocate objects when they want them to go away Adapt Hans Boehm's conservative garbage collector for C to C++ C++ constructors and destructors are useful for automating certain types of memory management ::: ::: 30 No solution is optimal, however, so storage management is often performed by hand" ugh ;- 31 C++ Object-Oriented Features C++ provides three characteristics generally associated with object-oriented programming: C++ Object-Oriented Features cont'd 1. Data Abstraction Package a class abstraction so that only the public interface is visible and the implementation details are hidden from clients C++'s object-oriented features encourage designs that Allow parameterization based on type 2. Speci c details of particular instantiations of these concepts 2. Single and Multiple Inheritance A derived class inherits operations and attributes from one or more base classes, possibly providing additional operations and or attributes 3. Dynamic Binding The actual type of an object and thereby its associated operations need not be fully known until run-time  Compare with C++ template feature, which are instantiated at compile-time 32 C++ Object-Oriented Features cont'd Color 1 Point 1 This approach facilitates extensibility and reusability 33 C++ Object-Oriented Features cont'd Program families are sets of programs whose common properties are so extensive that it is advantageous to study the common properties of the programs before analyzing individual members Shape 1 e.g., an object-oriented graphical shapes library design using inheritance and dynamic binding Inheritance and dynamic binding facilitate the construction of program families" and frameworks Rectangle Triangle Circle 1. Explicitly distinguish general properties of related concepts from A A framework is an integrated set of components that collaborate to product a reuseable architecture for a family of related applications 1 Note, the OOD challenge" is to map arbitrarily complex system architectures into inheritance hierarchies 34 It also supports the open closed principle i.e., open with respect to extensibility, closed with respect to stability 35 Inheritance Preview A type can inherit or derive the characteristics of another base type. These derived types act just like the base type, except for an explicit list of: 1. Operations that are implemented di erently, i.e., overridden 2. Additional operations and extra data members 3. Modi ed method access privileges C++ supports both single and multiple inheritance, e.g., class X f * * g; class Y : public X f * * g; class Z : public X f * * g; class YZ : public Y, public Z f * ::: Inheritance Example: Ada-style Vectors * File Ada Vector.h still incomplete wrt assignment and initialization * if !de ned  ADA VECTOR H de ne ADA VECTOR H include "Vector.h" template class T class Ada Vector : private Vector T f public: Ada Vector int l, int h; T &operator int i; extend visibility from class Vector Vector::size; Vector::RANGE ERROR; Note, destructor is not inherited private: int lo bnd ; g; endif * ADA VECTOR H * ::: ::: ::: ::: * g; 36 Inheritance Example: Ada-style Vectors cont'd * File Ada Vector.C * template class T Ada Vector T ::Ada Vector int l, int h : lo bnd l, Vector T h , l + 1 fg template class T T &Ada Vector T ::operator int i f if this- in range i , this- lo bnd  Call inherited operation, no range checking return this- elem i , this- lo bnd ; else throw Ada Vector T ::RANGE ERROR ; * or *this i , this- lo bnd ; * 37 Inheritance Example: Ada-style Vectors cont'd Example Ada Vector Usage File main.C include stream.h include "Ada Vector.h" extern "C" int atoi const char *; int main int argc, char *argv  f try f int lower = atoi argv 1 ; int upper = atoi argv 2 ; Ada Vector int ada vec lower, upper; ada vec lower = 0; for int i = lower + 1; i = ada vec.size ; i++ ada vec i = ada vec i , 1 + 1; Run-time error, index out of range ada vec upper + 1 = 100; g 38 g Vector destructor called when ada vec goes out of scope g catch Ada Vector int ::RANGE ERROR f * 39 ::: * Dynamic Binding Preview cont'd Dynamic Binding Preview Dynamic binding is a mechanism used along with inheritance to support a form of polymorphism C++ uses virtual functions to implement dynamic binding: The actual method called at run-time depends on the class of the object used when invoking the virtual method C++ allows the class de ner the choice of whether to make a method virtual or not This leads to time space performance vs. exibility tradeo s  Virtual functions introduce a small amount of overhead for each virtual function call e.g., struct X f * Base class * int f void f puts "X::f"; g Non-virtual virtual int vf void f puts "X::vf"; g Virtual g; struct Y : public X f * Derived class * int f void f puts "Y::f"; g Non-virtual virtual int vf void f puts "Y::vf"; g Virtual g; void foo X *x f * Note, can also use references * g x- f ; * direct call: f 1X x; * x- vf ; * indirect call: *x- vptr 1  x * ::: int main void f g X x; Y y; foo &x; foo &y; X::f, X::vf X::f, Y::vf 40 41 New-Style Comments Dynamic Binding Preview cont'd C++ allows two commenting styles: Each class with 1 or more virtual functions generates one or more virtual tables vtables Note, multiple inheritance creates multiple vtables A vtable is logically an array of pointers to methods A vtable is typically implemented as an array of pointers to C functions Each object of a class with virtual functions contains one or more virtual pointers vptrs, which point at the appropriate vtable for the object The constructor automatically assigns the vptrs to point to the appropriate vtable 42 1. The traditional C bracketed comments, which may extend over any number of lines, e.g., * This is a multi-line C++ comment * 2. The new continue until end-of-line" comment style, e.g., This is a single-line C++ comment Note, C-style comments do not nest * * Hello world program * int main void f printf "hello world n"; g * However, these two styles nest, so it is possible to comment out code containing other comments, e.g., * assert i size check index range * if i != 0 * check for zero divide * && 10 i 43 New-Style Comments cont'd Naturally, it is still possible to use C C++ preprocessor directives to comment out blocks of code: if 0 * Make sure only valid C++ code goes here! * * i.e., don't use apostrophes! * endif Beware of subtle whitespace issues ::: int b = a * divided by 4 * 4; Type-safe linkage allows the linker to detect when a function is declared and or used inconsistently, e.g.,: File abs.c long abs long arg f return arg 0 ? -arg : arg; g File application.c include stdio.h int abs int arg; int main void f printf "d n", abs ,1; g -a; * C++ preprocessing and parsing. * int b = a -a; * C preprocessing and parsing. * int b = a 4; -a; Note, in general it is best to use whitespace around operators and other syntactic elements, e.g., char *x; int foo char * = x; OK int bar char*=x; Error Type-Safe Linkage Without type-safe linkage, this error would remain hidden until the application was ported to a machine where ints and longs were di erent sizes e.g., Intel 80286 45 44 Type-Safe Linkage cont'd Type-Safe Linkage cont'd Type-safe linkage encodes all C++ function names with the types of their arguments a.k.a. name mangling"! Name mangling was originally created to support overload resolution e.g., Only function names are mangled i.e., variables, constants, enums, and types are not mangled long abs long arg ! abs Fl int abs int arg ! abs Fi :: : Therefore, the linker may be used to detect mismatches between function prototypes, function de nitions, and function usage 46 On older C++ compilers, diagnostic messages from the linker are sometimes rather cryptic! See the c++filt program :: : 47 Typesafe Linkage cont'd Typesafe Linkage cont'd Language interoperability issues This problem arises as a side e ect of using type-safe linkage in C++ C functions used in C++ code e.g., standard UNIX library functions must be explicitly declared as requiring C linkage i.e., names are not mangled via the new extern "C" declaration e.g., Complex abs Complex &c; int foo int bar f abs Complex ,10, 4.5; calls abs F7Complex abs bar calls abs abs 3.1416 calls abs Fd g Other syntactic forms of extern blocks: extern "C" f char *mktemp const char *; char *getenv const char *; g Encapsulating existing header les if de ned  cplusplus extern "C" f endif * cplusplus * include string.h ifdef cplusplus g endif * cplusplus * Note, extern blocks also support other languages extern "C" int abs int i; double abs double d; cout Language interoperability issues cont'd :::  e.g., FORTRAN, Pascal, Ada, etc. 48 Inline Functions Many programming languages force developers to choose between: 1. Modularity abstraction function call 2. Performance macro or inline-expansion by-hand C++ allows inline function expansion, which has several advantages: 1. It combines the e ciency of a macro with the type-security and abstraction of a function call 49 Inline Functions cont'd Here's an example of a common C problem with the preprocessor: Classic C macro, no sanity-checking at macro expansion time de ne SQUAREX X * X int a = 10; int b = SQUARE a++; trouble!!! a++ * a++ C++ inline function template 2. It reduces both execution time and code size potentially template class T inline T square T x f return x * x; g 3. It discourages the traditional reliance upon macro preprocessor statements int c = square a++; 50 OK 51 Inline Functions cont'd Inline Functions cont'd Points to consider about inline functions: 1. Class methods that are de ned in their declaration are automatically expanded inline 2. It is di cult to debug code where functions have been inline expanded and or optimized 3. Compilers require more time and space to compile when there are many inline functions 4. Inline functions do not have the pseudo-polymorphic properties of macros However, inline templates approximate this functionality 5. Compilers often have limits on the size and type of function that can be inlined. e.g., if stack frame is very large: int foo void f int local array 1000000 ; This can cause surprising results wrt code size, e.g., int bar void f foo ; foo ; g ::: 52 As an example of inlining in C++, we will discuss a simple run-time function call trace" facility Provides a rudimentary debugging facility  e.g., useful for long-running network servers The goals are to be able to: 1. Determine the dynamic function calling behavior of the program, i.e., tracing" 2. Allow for ne-grain control over whether tracing is enabled, e.g., At compile-time remove all traces of Trace and incur no run-time penalty At run-time via signals and or commandline options 3. Make it easy to automate source code instrumentation 53 Inline Functions cont'd Example output: e.g., write a regular expression to match function de nitions and then insert code automatically  CC -D__INLINE__ main.C trace.C  a.out 10 1 enter int main int argc, char *argv  in file main.C on line 25 enter void foo void file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 enter void foo void in file main.C, line 8 leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave void foo void leave int main int argc, char *argv  54 Inline Functions cont'd Inline Functions cont'd Trace.h e.g., main.C include "Trace.h" void foo int max depth f g T "void foo void"; * Trace "void foo void", 8, "main.c" * if max depth 0 foo max depth , 1; * Destructor called automatically * int main int argc, char *argv  f const int MAX DEPTH = argc == 1 ? 10 : atoi argv 1 ; if argc 2 Trace::set nesting indent atoi argv 2 ; if argc 3 g Trace::stop tracing ; T "int main int argc, char *argv "; foo MAX DEPTH; return 0; * Destructor called automatically * 55 if !de ned  TRACE H de ne TRACE H if de ned NTRACE compile-time omission de ne TX else de ne TX Trace X, LINE , FILE  endif * NTRACE * class Trace f public: Trace char *n, int line = 0, char * le = ""; ~Trace void; static void start tracing void; static void stop tracing void; static int set nesting indent int indent; private: static int nesting depth ; static int nesting indent ; static int enable tracing ; char *name ; g; if de ned  INLINE  de ne INLINE inline include "Trace.i" else de ne INLINE endif * INLINE * endif * TRACE H * 56 Inline Functions cont'd Inline Functions cont'd e.g., * Trace.C * e.g., * Trace.i * include "Trace.h" include stdio.h INLINE Trace::Trace char *n, int line, char * le f if Trace::enable tracing  fprintf stderr, "*senter s  le s, line d n", Trace::nesting indent * Trace::nesting depth ++, "", this- name = n, le, line; g if !de ned  INLINE  include "Trace.i" endif * INLINE * INLINE Trace::~Trace void f if Trace::enable tracing  fprintf stderr, "*sleave s n", Trace::nesting indent * --Trace::nesting depth , "", this- name ; g * Static initializations * int Trace::nesting depth = 0; int Trace::nesting indent = 3; int Trace::enable tracing = 1; void Trace::start tracing void g Trace::enable tracing = 1; void Trace::stop tracing void f g Trace::enable tracing = 0; int Trace::set nesting indent int indent f int result = Trace::nesting indent ; Trace::nesting indent = indent; return result; g 57 58 Dynamic Memory Management Dynamic memory management is now a built-in language construct, e.g., Traditional C-style void *malloc size t; void free void *; int *a = malloc 10 * sizeof *a; free void * a; C++ syntax int *a = new int 10 ; int *b = new int; delete a; delete b; Const Type Quali er C++ data objects and methods are quali able with the keyword const, making them act as read-only" objects e.g., placing them in the text segment" const only applies to objects, not to types ::: e.g., const char *foo = "on a clear day"; char *const bar = "you can C forever!"; const char *const zippy = "yow!"; ::: Built-in support for memory management improves: 1. Type-security 2. Extensibility 3. E ciency 59 foo = "To C or not to C?" OK foo 7 = 'C'; error, read-only location error, can't assign to const pointer bar bar = "avoid cliches like the plague."; OK, but be careful of read-only memory!!! bar 1 = 'D'; const int index = 4 , 3; index == 1 read-only an array of constant ints const int array index + 3 = f2, 4, 8, 16g; 60 Const Type Quali er cont'd Const Type Quali er cont'd User-de ned const data objects: const methods A const quali er can also be applied to an object of a user-de ned type, e.g., const String string constant "Hi, I'm read-only!"; const Complex complex zero 0.0, 0.0; string constant = "This will not work!"; ERROR complex zero += Complex 1.0; ERROR complex zero == Complex 0.0; OK const methods may specify that certain readonly operations take place on user-de ned const objects, e.g., class String f public: size t size void const f return this- len ; g void set size t index, char new char; private: size t len; g; ::: Ensuring const correctness" is an important aspect of designing C++ interfaces, e.g., 1. It ensures that const objects may be passed as parameters 2. It ensures that data members are not accidentally corrupted 61 const String string constant "hello"; string constant.size ; Fine A const method may not directly modify its this pointer string constant.set 1, 'c'; Error 62 Stream I O Stream I O cont'd C++ extends standard C library I O with stream and iostream classes Several goals 1. Type-Security Reduce type errors for I O on built-in and user-de ned types The stream and iostream class categories replace stdin, stdout, and stderr with cout, cin, and cerr These classes may be used by overloading the and operators Transparently add new underlying I O devices to the iostream model C++ does not get a segmentation fault since the "correct" function is called include iostream.h char *name = "joe"; int id = 1000; cout "name = " name ", id = " id ' n'; cout.operator "name = ".operator "joe" In contrast, old C-style I O o ers no protection from mistakes, and gets a segmentation fault on most systems!  i.e., share higher-level formatting operations printf "name = s, id = s n", name, id; 2. Extensibility both above and below Allow user-de ned types to interoperate syntactically with existing printing facilities  Contrast with printf scanf-family ::: 64 63 Boolean Type Stream I O cont'd C++ has added a new build-in type called bool Be careful using Stream I O in constructors and destructors for global or static objects, due to unde ned linking order and elaboration problems ::: In addition, the Stream I O approach does not work particularly well in a multi-threaded environment ::: This is addressed in newer compilers that o er thread-safe iostream implementations The bool values are called true and false Converting numeric or pointer type to bool takes 0 to false and anything else to true bool promotes to int, taking false to 0 and true to 1 Statements such as if and while are now converted to bool All operators that conceptually return truth values return bool  e.g., the operands of &&, jj, and !, but not &, j, and ~ 65 66 References C++ allows references, which may be: References cont'd 1. Function parameters 2. Function return values 3. Other objects e.g., consider a swap abstraction: A reference variable creates an alternative name a.k.a. alias" for an object int main void f int a = 10, b = 20; void swap int x, int y f int t = x; x = y; y = t; References may be used instead of pointers to facilitate: g g printf "a = d, b = d n", a, b; swap a, b; printf "a = d, b = d n", a, b; 1. Increased code clarity 2. Reduced parameter passing costs 3. Better compiler optimizations There are several problems with this code References use call-by-value syntax, but possess call-by-reference semantics 3. It only works for integers! 1. It doesn't swap! 2. It requires a function call 67 68 References cont'd References cont'd e.g., swap e.g., swap void swap int *xp, int *yp f int t = *xp; *xp = *yp; *yp = t; g int main void f int a = 10, b = 20; template class T inline void g swap T &x, T &y f T t = x; x = y; y = t; g printf "a = d, b = d n", a, b; swap &a, &b; printf "a = d, b = d n", a, b; de ne SWAPX,Y,T do fT = X; X = Y; Y = ;g while 0 int main void f int a = 10, b = 20; printf "a = d, b = d n", a, b; SWAP a, b, int; beware of a++! printf "a = d, b = d n", a, b; g 69 int main void f int a = 10, b = 20; double d = 10.0, e = 20.0; g printf "a = d, b = d n", a, b; printf "d = f, e = e n", d, e; swap a, b; swap d, e; printf "a = d, b = d n", a, b; printf "d = f, e = e n", d, e; 70 References cont'd ir Type Cast Syntax i C++ introduces a new type cast syntax in addition to Classic C style casts. This "function-call" syntax resembles the type conversion syntax in Ada and Pascal, e.g., 10 With references as with classes, it is important to distinguish initialization from assignment, e.g., function prototype from math.h library extern double log10 double param; if int log10 double 7734 != 0 int i = 10; initialization of ir int &ir = i; Equivalent to int *const ip = &i; ir = ir + 10; ; * C style type cast notation * dereference is automatically done *ip = *ip + 10; Once initialized, a reference cannot be changed i.e., it may not be reassigned to reference a new location Note, after initialization all operations a ect the referenced object  i.e., not the underlying const pointer if int log10 double 7734 != 7734 ; C++ function-style cast notation This function call" is performed at compile time ::: 72 71 Type Cast Syntax cont'd Type Cast Syntax cont'd This type cast syntax is also used to specify explicit type conversion in the C++ class mechanism Note, there are a variety of syntactical methods for constructing objects in C++, e.g., This allows multiple-argument casts, i.e., constructors" 1. Complex c1 = 10.0; e.g.,: 2. Complex c2 = Complex 10.0; class Complex f public: Complex double, double = 0.0; private: double real, imaginary; 3. Complex c3 = Complex 10.0; 4. Complex c4 10.0; ::: I recommend version 4 since it is the most consistent and also works with built-in types g; Convert 10.0 and 3.1416 into a Complex object Complex c = Complex 10.0, 3.1416; It also generalizes to multiple-argument casts Note that old-style C syntax would not su ce here Complex c = Complex 10.0, 3.1416; ::: 73 74 ::: ::: Default Parameters cont'd Default Parameters C++ allows default argument values in function de nitions Default parameter passing semantics are similar to those in languages like Ada: e.g., only trailing arguments may have defaults * Incorrect * int x int a = 10, char b, double c = 10.1; Note, there is no support for named parameter passing" If trailing arguments are omitted in the actual function call these values are used by default, e.g., void assign grade char *name, char *grade = "A"; additional declarations and de nitions ::: assign grade "Bjarne Stroustrup", "C++"; Bjarne needs to work harder on his tasks However, it is not possible to omit arguments in the middle of a call, e.g., assign grade "Jean Ichbiah"; Jean gets an "A" for Ada! extern int foo int = 10, double = 2.03, char = 'c'; Default arguments are useful in situations when one must change a class without affecting existing source code e.g., add new params at end of argument list and give them default values foo 100, , 'd'; * ERROR!!! * foo 1000; * OK, calls foo 1000, 2.03, 'c'; There are several arcane rules that permit successive redeclarations of a function, each time adding new default arguments 75 Declaration Statements cont'd Declaration Statements C++ allows variable declarations to occur anywhere statements occur within a block The motivations for this feature are: 1. To localize temporary and index variables 2. Ensure proper initialization This feature helps prevent problems like: f 76 The following example illustrates declaration statements and also shows the use of the scope resolution" operator include iostream.h struct Foo f static int var; g; int Foo::var = 20; const int MAX SIZE = 100; int var = 10; int main void f int k; k = call something ; Note the use of the scope resolution" operator :: to access the global variable var int var = ::var , k + Foo::var; int i, j; * many lines of code * Oops, forgot to initialize! while i j * * ; ::: ::: g Instead, you can use the following f g for int i = var; i MAX SIZE; i++ for int j = 0; j MAX SIZE; j++ f int k = i * j; cout k; double var = k + ::var * 10.4; for int i = x, j = y; i j;  * ::: *; 77 g g cout var; 78 Abbreviated Type Names Declaration Statements cont'd However, the declaration statement feature may encourage rather obscure code since the scoping rules are not always intuitive or desirable Note, new features in ANSI C++ allow de nitions in the switch, while, and if condition expressions ::: According to the latest version of the ANSI ISO C++ draft standard, the scope of the definition of i in the following loop is limited to the body of the for loop: f ::: g ::: struct Tree Node f * C code * int item ; struct Tree Node *l child , * child ; g; struct Tree Node f * C++ code * int item ; g *; Another way of looking this is to say that C++ automatically typedefs tag names, e.g., typedef struct Tree Node Tree Node; struct Bar f * * g; struct Foo f g; typedef struct Foo Bar; ::: 79 Illegal C++, legal C! 80 User-De ned Conversions cont'd User-De ned Conversions The motivation for user-de ned conversions are similar to those for operator and function overloading e.g., reduces tedious" redundancy in source code However, both approaches have similar problems with readability ::: User-de ned conversions allow for more natural looking mixed-mode arithmetic for user-de ned types, e.g.,: Complex a = Complex 1.0; Complex b = 1.0; implicit 1.0 - Complex 1.0 a = b + Complex 2.5; a = b + 2.5 implicit 2.5 - Complex 2.5 String s = a; Tree Node *l child , *r child ; Note, this C++ feature is incompatible with certain Classic and ANSI C identi er naming conventions, e.g., for int i = 0; i 10; i++ * *; for int i = 0; i 20; i++ * Unlike C, C++ allows direct use of userde ned type tag names, without requiring a preceding union, struct, class, or enum speci er, e.g., implicit a.operator String  81 Conversions come in two avors: 1. Constructor Conversions: Create a new object from objects of existing types 2. Conversion Operators: Convert an existing object into an object of another type e.g., class Complex f public: Complex double; operator String ; g; ::: convert double to Complex convert Complex to String int foo Complex c f g c = 10.0; c = Complex 10.0; String s = c; c.operator String ; cout s; 82 Static Initialization User-De ned Conversions cont'd In C, all initialization of static objects must use constant expressions, e.g.,: In certain cases, the compiler will try a single level of user-de ned conversion to determine if a type-signature matches a particular use, e.g., class String f public: String const char *s; String &operator += const String &; g; String s; s += "hello"; s += String "hello"; Note, it is easy to make a big mess by abusing the user-de ned conversion language feature ::: Especially when conversions are combine with templates, inheritance virtual functions, and overloading, etc. int i = 10 + 20; * le scope * int foo void f static int j = 100 * 2 + 1; * local scope * g However, static initializers can be comprised of arbitrary C++ expressions, e.g., extern int foo void; le scope int a = 100; int i = 10 + foo ; int j = i + *new int 1; int foo void f static int k = foo ; return 100 + a; g Note, needless to say, this can become rather cryptic, and the order of initialization is not well de ned between modules 84 83 Miscellaneous Di erences In C++, sizeof 'a' == sizeof char; in C, sizeof 'a' == sizeof int This facilitates more precise overloading ::: char str 5 "hello" is valid C, but C++ gives error because initializer is too long because of hidden trailing ' 0' = In C++, a function declaration int f; means that f takes no arguments same as int fvoid;. In C it means that f can take any number of arguments of any type at all! C++ would use int f  ; ::: In C++, a class may not have the same name as a typedef declared to refer to a di erent type in the same scope 85 Miscellaneous Di erences cont'd In C++, a struct or class is a scope; in C a struct, enum, or enum literal are exported into the global scope," e.g., struct Foo f enum Bar fBAZ, FOOBAR, BIZBUZZg; g; * Valid C, invalid C++ * enum Bar bar = BAZ; Valid C++, invalid C Foo::Bar bar = Foo::BAZ; The type of an enum literal is the type of its enumeration in C++; in C it is an int, e.g., * True in C, not necessarily true in C++. * sizeof BAZ == sizeof int; * True in C++, not necessarily true in C. * sizeof Foo::BAZ == sizeof Foo::Bar; 86 Miscellaneous Di erences cont'd Summary In ANSI C, a global const has external linkage by default; in C++ it has internal linkage, e.g., * In C++, global1" is not visible to other modules. * const int global1 = 10; * Adding extern makes it visible to other modules. * extern const int global2 = 100; In ANSI C, a void * may be used as the right-hand operand of an assignment or initialization to a variable of any pointer type, whereas in C++ it may not without using a cast  ::: void *malloc size t; * Valid C, invalid C++ * int *i = malloc 10 * sizeof *i; * Valid C, valid C++ * int *i = int * malloc 10 * sizeof *i; C++ adds many, many, many new features to the C programming language It is not necessary to use all the features in order to write e cient, understandable, portable applications C++ is a moving target" Therefore, the set of features continues to change and evolve However, there are a core set of features that are important to understand and are ubiquitous 87 88 ...
View Full Document

{[ snackBarMessage ]}

Ask a homework question - tutors are online