# A C++ Crash Course Part II UW Association for Computing Machinery Questions & Feedback.

## Presentation on theme: "A C++ Crash Course Part II UW Association for Computing Machinery Questions & Feedback."— Presentation transcript:

A C++ Crash Course Part II UW Association for Computing Machinery http://www.cs.washington.edu/orgs/acm/tutorials acm@cs.washington.edu Questions & Feedback to Albert J. Wong (awong)

What We Will Cover C Preprocessor –#include, #define, #if, etc. –__FILE__, __LINE__ Multiple File Development –Header Files –Separate Compilation Compilation Process –Compilation –Linking Advanced Modifiers –const, static, extern, volatile Namespaces Operator Overloading Classes –Constructors, Destructors –Inheritance –Virtual (dynamic dispatch) Dynamic Memory –new, delete, delete[] –malloc, calloc, realloc, free C/C++ I/O Functions

What We Are NOT Covering Anything in the first tutorial –Pointers, arrays, references –structs, unions, enums Weird Inheritance –Multiple inheritance –Virtual inheritance (NOT dynamic dispatch) Templates –Generic Programming Exceptions STL Makefiles

Basics refresher Quiz Write a struct called Point3D that represents a 3D point. Give it 3 member variables, x, y, z with type double. Given that struct definition, and following code: –Count how many times a Point3D is created –List all places memory is allocated, and the type of memory allocated typedef struct Point3D Point3D; Point3D add(Point3D *a, Point3D *b) { Point3D p; p.x = a->x + b->x; p.y = a->y + b->y; return p } int main(void) { Point3D p1 = {0,1}; Point3D p2 = {3,4}; Point3D p3 = add(&p1, &p2); return 0; }

Declarations - (bad) Example int main(void) { int result;... result = add(20, 3);... return 0; } int add(int a, int b) { return a + b; } What is wrong with the following code? Will it compile in C? in C++? Hint: It has to do with the declaration and use of add.

Declaration Regions int main(void) { int result; int add(int,int);... result = add(20, 3);... return 0; } int add(int a, int b) { return a + b; }... int add(int,int); int main(void) { int result;... result = add(20, 3);... return 0; } int add(int a, int b) { return a + b; }... add is declared in the shaded regions Corrected Code 1 (local prototype) Corrected Code 2 (global prototype)

Declarations and definitions are separate concepts Declarations - Summary Declarations can be separate from definitions Function declarations are called prototypes Declarations should be given before usage C & C++ handle undeclared functions differently –In C++ this is an error –In C, the function is implicitly declared with the type: int name(...); Dangerous!

C-style IO is an acquired taste. Learn to like it. I/O C-style Basic functions: printf, scanf, fprintf, fscanf, sprintf, sscanf, etc. gets, puts, getc, putc, getchar read, write, fread, fwrite We will cover the basics of the formated family of functions (printf, scanf, etc). For the others, read the man pages in Unix.

printf(char *format_string,...); fprintf(FILE*, char *format_string,...); snprintf(char* buf, size_t n, char *format_string,...); printf In C, all devices are treated like files Three standard files are: –stdin Often the keyboard –stdout Often the text console –stderr Often the text console printf(....) is fprintf(stdout,....) The format string is a pattern for the output; it describes how to display the arguments to printf. Snprintf write to the string buf. The variable n specifies the size of the buffer. printf returns the number of characters written

format string Format strings are normal strings with embedded conversion specifications which are placeholders for arguments Conversion specifications are a % and a letter with an optional set of arguments in between the % and letter. To print a %, you need to write % Example: printf(Here is a number: %d\n, 10); %d is the conversion specification for signed integers.

Conversion Specifications Conversion Specifications: %d, %i -- signed integer %u -- unsigned integer %f -- floating point number %c -- character %s -- string %x -- hexadecimal value %p -- pointer Converion specifications tell how to translate a data value into a string Options: l -- long (32-bit value) ll -- long long (64-bit value) n -- field width of n digits.n -- precision of n digits 0 -- fill unused field with 0s There are many more! Read man pages, or Google it.

printf quiz! Figure out the output of the following: printf(%.3f rounded to 2 decimals is %.2f\n, 2.325, 2.325); printf(%d in hex is: %04x\n, 24, 24); printf(Quizzes are fun, ja?\n);

scanf(char *format_string,...); fscanf(FILE*, char *format_string,...); sscanf(char*, char *format_string,...); scanf scanf(....) is fscanf(stdin,....) All arguments ot scanf must be pointers (or arrays) scanf does almost no size checks. It is easy to get a buffer overflow here. Make sure you use a field length specifier with the %s conversion specifer!!! scanf returns the number of items read.

scanf Examples int items_read; Read a number: int num; items_read = scanf(%d, &num); Read a character: char ch; items_read = scanf(%c, &ch); Read a string of max length, 79 chars: char buf[80]; buf[79]=\0; // Ensure a terminating NULL. items_read = scanf(%79s, buf); Read number after pattern of a: : int num; items_read = scanf(a:%d, &num); always check the return value of scanf

C++-style IO is easier for simple stuff I/O C++-style Basic classes: iostream (cout, cin, cerr) ostringstream, istringstream cout << Hello World! << endll; cout << Boo! << 10 << c << endl; cerr << Heres the error stream << endl; int n; cin >> n; char ch; cin >> ch;

...but harder for complex stuff I/O C++-style continued... printf(%.3f rounded to 2 decimals is %.2f\n, 2.325, 2.325); …becomes… cout << setprecision(3) << 2.325 << rounded to 2 decimals is << setprecision(2) << 2.3.25 << endl;

C and C++ I/O compared C-style I/O: No type safety. What happens with printf(%d, c); ? Conversion specifications have a high learning curve. Almost all the state of the I/O is contained in the function call. C++ style I/O: Manipulators are very verbose/annoying Global state gets changed. When you do cout << 2.4555, what precision are you set at? You dont know. Its worse with threads. You get more customizability since C++ I/O is classed based. NEVER mix C and C++ I/O...until you know what ios::sync_with_stdio() does.

Multiple File Development Related functions and variables can be grouped into different files Each file is considered a module There is no enforced relation between the filename and its contents! int add(int a, int b); int main(void) { int result; printf(%d\n, add(a,b)); return 0; } int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } main.ccutils.cc

The compilation Process Preprocessor.c.h.c.h Compiler Linker executable Libraries Source code (text) C/C++ code (text) Object code (bin) Native Executable (bin) Preprocesser Resolves #define, #include Compiler Translates code to Machine Language. It outputs an object file. This code is not executable Linker Takes object files and resolves references to functions and variables in different files

Compilation in Unix The following commands perform the whole compilation process for C and C++: gcc -Wall -g file1.c file2.c -o progname g++ -Wall -g file1.cc file2.cc -o progname You can control which stages get run: Only run the preprocessor gcc -E file.c Only run the compiler (dont link) gcc -Wall -ansi -c file.c Link these files gcc file1.o file2.o -o progname

Common Compilation options -Wall enable all warnings -ansi turn on strict ansi compliance -v verbose mode on. (lists which directories were searched for include files and libraries) -g generate debugging symbols -c compile only (create object file) -E run the preprocessor only -s generate assembly code (instead of object code) -I prepend directory to include path -L prepend directory to library path -l library to link (looks for lib.so, or.a, or.la) in library path -o specifies output filename -O[n] specifies optimization level (default 0) -D [=value] define the give preprocessor Tag Always specify -Wall and -g : gcc -Wall -g

Preprocessor and Compiler Preprocessor –Does not understand C/C++ –Produces text that gets read by the compiler Compiler –Expects pure C/C++ (no preprocessor stuff) –Checks syntax –Typechecks your code –Generates, and optimizes, machine code –Produces object files for the linker –Still knows what source file and line numbers

Linker –Resolves dependencies between object files –Places functions, variables, in final location –Generates executables –Does no code optimization –Knows nothing about source files (filenames or line numbers) –Knows nothing about types –Matches dependencies by name alone –In C++, linker symbols have been mangled by the compiler (name mangling) to include the return type and argument types. This allows for overloading. –Name mangling is compiler dependent. The linker may not be able to link objects from different compilers.

Object Files Object files contain compiled code plus an index stating what symbols it has, and what symbols it needs Use nm (unix) and dumpbin (windows) to list the index The linker look at all the the object files and tries to find a one-to-one mapping of needs symbol to a has symbol.dll and.so files (windows and unix respectively) are object files with special indexes that the OS can understand and use at runtime. Object File extensions:.o,.obj

Identify who gave the error Error 1: test.c:1:10: #include expects "FILENAME" or Error 2: /tmp/ccdoe7a7.o: In function `main': /tmp/ccdoe7a7.o(.text+0x7): undefined reference to `foo' collect2: ld returned 1 exit status Error 3: test.c: In function `main': test.c:4: `iii' undeclared (first use in this function) test.c:4: (Each undeclared identifier is reported only once test.c:4: for each function it appears in.) test.c:4: parse error before `989' Error 4: /tmp/ccwltu5R.o: In function `foo': /tmp/ccwltu5R.o(.text+0x0): multiple definition of `foo' /tmp/ccx3bPfI.o(.text+0x0): first defined here collect2: ld returned 1 exit status

Break Stand up Stretch Play with stuff animals Next topics: –Header Files –Preprocessor

Header Files Common Usages: Creates an informal module interface (No relation to Java interfaces) Provides documentation Each module usually has a header file Often include the following: –function prototypes –struct and class declarations –typedefs –global variable declarations –Lots of (high-level) comments Abstracts code for optimization (less common)

Header File Example (has error) point2d.h struct Point2D { int x; int y; }; typedef struct Point2D Point2D; /* returns the result of the vector addition of * a and b. */ Point2D add(Point2D *a, Point2D *b); /* returns the result of the vector subtraction of * b from a */ Point2D sub(Point2D *a, Point2D *b); There is a subtle problem with this header file. It is shown on the next slide.

Header File Problem output.h #include point2d.h #include point3d.h /* pretty print the different point types to * stdout. */ void Point2D_prettyPrint(Point2D *p); void Point3D_prettyPrint(Point3D *p); main.h #include point2d.h #include output.h int main(void) { Point2D p; p.x = 3; p.y = 5; Point2D_prettyPrint(&p); return 0; } We get a compile error. Multiple definition of struct Point2D We use the preprocessor to fix this

Preprocessor Overview The preprocessor is a lexical macro engine run before the compiler sees the code Performs lexical transforms of text –It does not understand C/C++ –There is no concept of types Transforms are based on lexical substitution –Think Search and Replace Preprocess directives (commands) start with # –Each directive goes on its own line –The # must be the first character on a line. No semicolons!!!!!!!!!!!! –Newlines end a preprocessor directive, no a ;.

#define #define Tag Substitution –Replaces all following occurrences of Tag with Substitution –The Substitution may be the empty string –Does not replace Tag if it is inside quotation marks #define Tag(x,y,z) Substitution –Creates a Function-like macro Tag –The Substitution may refer to the parameters x, y, or z –Only items of the form Tag(x,y,z) will be replaced (Just plain Tag will be ignored) #define MAX_SIZE 80 #define GET_FIELD(a,b) a->b int ar[MAX_SIZE]; GET_FIELD(point, xCoord); GET_FIELD(lalala", f03j?); int ar[80]; point->xCoord lalala->f03j?

The #if, and its variants #if constant-expression Include the following block of text if constant-expression is non-zero #ifdef Tag Include the following block if Tag is currently defined (via an earlier #define ) #ifndef Tag Include the following block if Tag is currently not defined (via an earlier #define )

#else, #elif, #endif #else Used to delimit the else clause in a preprocessor if statement #elif constant-expression Used to create an else-if clause in a preprocessor if statement #endif Delimits the end of a preprocessor if statement. There should be exactly one of these for each #if, #ifdef, and #ifndef.

#if examples #ifdef INCLUDE_DEBUG_PRINT # define DPRINT(msg) \ fprintf(stderr, DBG: %s, msg); #else # define DPRINT(msg) #endif #ifdef WIN32 # define open _open # define close _close #endif The DPRINT macro when INCLUDE_DEBUG_PRINT is defined, evaluates to printing code. Otherwise, it evaluates to the empty string. Windows calls the open and close functions, _open, and _close respectively. This is annoying, so lets fix it with preprocessor macros.

#include #include essentially copies and pastes the given file into the current line There are two forms of #include They differ in the order in which directories are search for the given file The search order is implementation defined Here is the general pattern for different compilers: #include Searches the include path, then the current directory #include filename Searches the current directory, then the include path

#undef, #error, #warning #undef Tag Removes definition of a Tag. (undoes a #define ) #error message Causes compilation to stop at this line with the given error message. Often this is used with #if blocks to indicate an invalid set of #define macros. #warning message Causes the compiler to output an warning at this line with the given message. Can be used as strong reminders that a file needs work. #pragma option Used to pass an option to the compiler. Almost all #pragma commands are compiler-dependent.

#pragma, #line #pragma option Used to pass an option to the compiler. Almost all #pragma commands are compiler-dependent. #line number Used to change what line number that the compiler thinks it is on. This is often seen in: Computer Generated Code (from like flex, bison, or something) Code outputed by the preprocessor #line to allows programs to make the compilers error messages to correspond to the original source files line numbers rather than the generated source files line numbers.

Useful Macros There are a few macros ( #defines ) that are given by the compiler that are very useful to know when trying to debug code. __FILE__ string literal of the current filename __LINE__ integer literal with the current line number __func__ string literal of the current function name __DATE__ string literal of the current date

Other Weird (But Useful) Notes If you need to break anything into multiple lines, end the line with a single \. The lexer (thing that reads the file) will concatinate the two lines for you. Avoid doing this unless you have no other choice. Multiple string literals in a row, with only whitespace separating them, are automatically concatinated. Hi Mom! Heres a String! In #define macros, you can get a quoted version of the input argument by prepending the argument with a #. #define mk_str(x) #x used as mk_str(hi) yields hi In #define macros, you can concatinate input arguments with ##. #define foo(a) a##foo used as foo(hi_) yields hi_foo

#define DBG_MKSTR(a) #a #define DBG_LOCATION_0(x) __FILE__ "," DBG_MKSTR(x) " -- " #define DBG_LOCATION DBG_LOCATION_0(__LINE__) #define LOCATION_STR(x) DBG_LOCATION x #if !NDEBUG #define LOG(level, msg, args...) \ if (g_debugLevel >= (level)) \ fprintf(stderr, \ #level ": " DBG_LOCATION msg, ##args) #else #define LOG(level, msg, args...) #endif #define INFO 0 #define WARNING 1 #define ERROR 2 Complex Example Usage: LOG(INFO, Program got here\n);

Complex Example Exercise LOG(INFO, Program got here\n); What is the output of the following line assuming NDEBUG is not defined? What is if it is definied? Assume the following: The filename is test.cc The line number is 123

Preprocessor Summary The preprocessor does lexical manipulations Preprocessor commands do not end in semicolons All preprocessor commands start with a # The most common (important) preprocessor directives are: #include, #define, and #ifndef Useful directives that are not used enough are: #error, and #warning. There are a number of provided macros that are very useful to know. In particular, know about __FILE__, __LINE__, __func__

(dup) Header File w/ subtle error point2d.h struct Point2D { int x; int y; }; typedef struct Point2D Point2D; /* returns the result of the vector addition of * a and b. */ Point2D add(Point2D *a, Point2D *b); /* returns the result of the vector subtraction of * b from a */ Point2D sub(Point2D *a, Point2D *b); There is a subtle problem with this header file. It is shown on the next slide.

(dup) Header File Problem output.h #include point2d.h #include point3d.h /* pretty print the different point types to * stdout. */ void Point2D_prettyPrint(Point2D *p); void Point3D_prettyPrint(Point3D *p); main.h #include point2d.h #include output.h int main(void) { Point2D p; p.x = 3; p.y = 5; Point2D_prettyPrint(&p); return 0; } We get a compile error. Multiple definition of struct Point2D We use the preprocessor to fix this

Header Guards Wrap each header file with the lines: #ifndef FILENAME_H #define FILENAME_H #endif /* FILENAME_H */ Header Guards are a common C/C++ idiom There is almost no reason to put things outside of header guards

Header File (corrected) point2d.h #ifndef POINT2D_H #define POINT2D_H struct Point2D { int x; int y; }; typedef struct Point2D Point2D; /* returns the result of the vector addition of * a and b. */ Point2D add(Point2D *a, Point2D *b); /* returns the result of the vector subtraction of * b from a */ Point2D sub(Point2D *a, Point2D *b); #endif /* POINT2D_H */

Header File Problem (fixed) output.h #ifndef OUTPUT_H #define OUTPUT_H #include point2d.h #include point3d.h /* pretty print the different point types to * stdout. */ void Point2D_prettyPrint(Point2D *p); void Point3D_prettyPrint(Point3D *p); #endif /* OUTPUT_H */ #include point2d.h #include output.h int main(void) { Point2D p; p.x = 3; p.y = 5; Point2D_prettyPrint(&p); return 0; } Error fixed since on the second #include of point2d.h, POINT2D_H has been defined and thus, its contents are skipped main.h The header guard for output.h never gets used, but you should still have it just incase.

Intermission Stretch Go use the restroom We restart in about 5 minutes Next topics: –Variables (globals, advanced modifiers) –Classes –Dynamic Memory

Dynamic Memory Dynamically sized memory in C and C++ must be manually managed Dynamic memory is not necessarily much slower than static memory All allocated memory must be freed by the user Do not free memory twice (double free). Do not free memory that was allocated by you Manual memory management allows for finer grained control of your program Its not that scary, nor that hard.

new, delete, delete[] the new operator allocates new memory, initializes it and returns a pointer to it. the delete operator deallocates memory allocated by new If you allocate a new array, you must delete it with delete[] and not delete Improper use of delete and delete[] will cause undefined behavior! Point2D *p = new Point; delete p; p = NULL; int *ar = new int[50]; delete[] ar; ar = NULL; Example:

malloc, calloc, realloc, free These are C memory management functions Do not mix them with the C++ ones! (that is, dont try to delete memory from malloc, etc.) These functions return void* (pointers to anything) They are not typesafe They do not call initializers for the memory There is no realloc equivalent for C++ Some low-level memory management may be faster with these functions, but dont bank on that.

Global Variables Global Variables are not evil! Allocated at program start. Deallocated at program end. By default, initialized to bit-wise zero (do not depend on this). Need to understand modifiers: extern, static, and const to use properly. Need to understand linking to use properly.

Global Variables - Gotcha I /* util.c */ int g_numCalls = 0; void someFunc(void) { fprintf(stderr, Num Calls to %s: %d\n, __func__, g_numCalls);... } What is wrong with this code? /* test.c */ void someFunc(void); int g_numCalls = 0; int main(void) { fprintf(stderr, Num Calls to %s: %d\n, __func__, g_numCalls); someFunc();... } compile line: gcc -Wall -ansi util.c test.c -o test

static On a global variable or a function static int g_someGlobalVariable; static void myFunction(void); Tells the linker not to export the variable or function. Essentially makes the identifier file scope, as the linker will not use it fulfill dependencies from other files. On a local (function) variable void someFunc(void) { static int array[4000]; } Places the variable off the stack. This has the side-effect that it retains it value across calls. It is often used when a variable is too large to be put on the stack. On a class member (covered when we discuss classes) static has 3 very separate meanings

Globals Variables - Gotcha I (fixed) /* util.c */ static int g_numCalls = 0; void someFunc(void) { fprintf(stderr, Num Calls to %s: %d\n, __func__, g_numCalls);... } Static to the rescue!!!!! /* test.c */ void someFunc(void); static int g_numCalls = 0; int main(void) { fprintf(stderr, Num Calls to %s: %d\n, __func__, g_numCalls); someFunc();... } compile line: gcc -Wall -ansi util.c test.c -o test The two variables g_numCalls have no relation. Think of them as private to each file.

Global Variables - Gotcha II /* debug.h */ int debug_level; … What is wrong with this code? /* test.c */ #include debug.h … compile line: gcc -Wall -ansi *.c -o test /* debug.c */ #include debug.h … /* otherfile.c */ #include debug.h …

Global Variables - Gotcha II (bad fix) /* debug.h */ static int debug_level; … /* test.c */ #include debug.h … compile line: gcc -Wall -ansi *.c -o test /* debug.c */ #include debug.h … /* otherfile.c */ #include debug.h … …but get 3 distinct copies of debug_level! bad! static with fix the compile error…

extern The problem is: – you want to declare int debug_level – you dont want to allocate space for it every time This is exactly what extern does. extern int debug_level; This means, there exists an int called debug_level, but the storage is not here. Go find it linker! Go! Function Prototypes are implicitly declared as extern ! As with prototypes, you must remember to actually declare the real variable somewhere (preferable in one implementation file ).

Global Variables - Gotcha II (good fix) /* debug.h */ extern int debug_level; … /* test.c */ #include debug.h … compile line: gcc -Wall -ansi *.c -o test /* debug.c */ #include debug.h int debug_level; … /* otherfile.c */ #include debug.h … Remember, you have to create the variable somewhere, hence the int debug_level in debug.c Ahh….All better.

const Unlike other globals, constant variables can be declared and allocated in the headers without problems. All const variables must be initialized at declaration. const is a compile-time feature; it is part of the type. const is mainly useful in association with references and pointers as parameters to functions. Since it is part of the type, you can cast it away Casting it away is a bad idea if the actual instance was initially created as const. Use const as often as possible! const int var = 0; void prettyPrintPoint(const Point2D &p); void prettyPrintPoint(const Point2D *p);

const Syntax oddities This means the ordering of const and * matter. Read modifiers from right to left. int * const p = &n; // constant pointer to an integer. The pointer, p, is constant, but the integer it points to is not. const is a type modifier (like * and &) int n; const int *p1 = &n; int const *p2 = &n; int * const p3 = &n; int *p4 = &n; p1 = p2; // ok. p1 and p2 have the same type. *p2 = 1; // Error. p2 is a pointer to a constant; p3 = p2; // Error. p3 is a constant pointer p4 = p2; // Error. p4 doesnt guarantee *p4 is const p1 = p3; // ok. p1 is a stronger restriction than p3

namespace Namespaces group functions and variables under a prefix Analogous to Java Packages (w/o access modification, or path restrictions) Used to avoid name collisions. Declared by: namespace { } All symbols (functions and variables) are under the prefix. Symbols accessed by ::symbol Namespaces can be nested. You can omit the :: when referring symbols from the same namespace, or a containing namespace.

using using directives influence the symbol lookup for namespaces Analogous to Java import statements There are 2 forms: –using ::symbol; –using namespace ; The first form tells the compiler that symbol means ::symbol. The second form tells the compiler to look for ::symbol if it cannot find symbol in the current namespace. NEVER put using directives in header files!!! Bad Form!! All standard library symbols are in the namespace std

Namespace example #include namespace Albert { void greet() { std::cout << Hi from Albert!; } } namespace Piyo { void greet() { std::cout << Peep from Piyo!; } void squeak() { std::cout << squeak! Squeak!; } } Albert:: greet(); // Hi from Albert! greet(); // Compile error. No symbol greet using Piyo::greet; greet(); // Peep From Piyo! Albert::greet(); // Hi From Albert! squeak(); // Compile error. No symbol squeak using namespace Piyo; greet(); // Peep From Piyo! Albert::greet(); // Hi From Albert! squeak(); // squeak! squeak!

Operator Overloading In C++, you can define operators ( +,-,*,/, etc.) for new types. Operators are usually binary, or unary functions. Examples of unary operators: !false, -i Examples of binary operators a + b, isBig || isRed The syntax for referring to the operator function is operator Here is the prototype for integer addition ( + ): int operator+(int lhs, int rhs);

Operator Overloading Example Point2D operator+(const Point2d &lhs, const Point2d &rhs) { Point2D p; p.x = lhs.x + rhs.x; p.y = lhs.y + rhs.y; return p; } What happens if I have the following prototype? Point2D operator+(Point2d lhs, Point2d rhs); How about this one? Point2D operator+(Point2d &lhs, Point2d &rhs);

Discussion Point What are the benefits of operator overloading? What are the drawbacks? Bonus Question: Are they necessary for C++?

Classes Roots come from C-style structs Fairly similar to Java classes in concept. Used to group related data and functions. Can be used to write OO code class Queue { public: Queue(); void enqueue(int n); int dequeue(); ~Queue(); private: int numElements; int capacity; int *queueData; };

Basic class Syntax Declaring a class: class [optional name] { [access modifier] member1; member2; [access modifier] member3; member4; … } [instance list]; Example: class Point2D{ private: int x; int y; public: Point2D(int x, int y); int getX(); int getY(); } p1(2,3); Point2D p2(1,3); Point2D *p; Declaring a class without inheritance

/* point2d.h */ #ifndef POINT2D_H #define POINT2D_H class Point2D{ private: int x; int y; public: Point2D(int x, int y); int getX(); int getY(); }; #endif /* POINT2D_H */ Declaring & Defining methods /* point2d.cc */ #include point2d.h Point2D::Point2D(int x, int y){ x = 0; y = 0; } int Point2D::getX(){ return x; } int Point2D::getY(){ return y; } Classes form a closed namespace

Constructors Constructors have the same name as their class Constructors may not pass off control to another constructor A default (zero argument) constructor is provided when no other constructors declared Constructors may invoke the constructors of their super class, and of their member variables via member-wise initialization. Constructors are functions that get called when a class is instantiated

Memberwise Initialization Memberwise Initialization changes what constructor gets called for members and parent classes Standard way: Point2D::Point2D(int x, int y){ x = 0; y = 0; } Memberwise Initialization (more C++) way: Point2D::Point2D(int x, int y) : x(0), y(0) {} The order matter. The order must match the order the variables are declared. To call a member variables constructor, specify the name of the variable, and then the arguments to the constructor To call a different parent class constructor, specify ParentClassName(args)

Destructors Destructors are called when a class is deallocated Destructors are have no return type and have the same name as their class with a ~ prepended. If no destructor is given, a trivial destructor, which calls the destructor for all elements is given.

Inheritance Inheritance is specified by a : and a list of access specifiers + class names in the class declaration class Point2D{ private: int x; int y; public: Point2D(int x, int y); int getX(); int getY(); }; class ColorPoint2D : public Point2D { private: int color; public: ColorPoint2D(int x, int y, int color); int getColor(); };

Inheritance continued Base classes can be public, protected, or private –In public inheritance, all public and protected members are inherited –In protected inheritance, all public members from the base class become protected –In private inheritance, all public and protected members become private Java only has public inheritance You can call any ancestors class method using the scope resolution operator ( :: )

Dynamic Dispatch By default, dynamic dispatch is not enabled in C++!! For a function to have dynamic dispatch, it must be declared virtual. If it is not declared virtual, then the static type when the function is called, (that is, the type of the pointer, or reference) is used to resolve the function. If you ever use any dynamic memory with a class, MAKE ITS DESTRUCTOR VIRTUAL! In general, it is safe to make all your functions virtual. Once a function is made virtual in a hierarchy, it cannot be made non-virtual later in the hierarchy.

Abstract Classes

Cannonical Form

Const

Weirdnesses static members

friends Classes and functions can be declared as friends by writing –friend ; Friends have access to a classs private members. Remember, only friends can touch each others private parts

Download ppt "A C++ Crash Course Part II UW Association for Computing Machinery Questions & Feedback."

Similar presentations