Anda di halaman 1dari 52

C++ Part II

Yingcai Xiao

TOC
Header files and Makefile Command line arguments: argc and argv Introduction to pointers: C++1.ppt Advanced pointer concepts Arrays Pointer arithmetic Functional pointers Virtual functions CORBA

C++ Preprocessing, Compilation and Linking

C++ Compilation
Source File (.cpp) Preprocessing

Intermediate File (.I) Compilation


Object File (.obj)

Linking
Binary File (.exe)

Preprocessing
copy everything in the include files into the .cpp file replace all symbolic constants remove all white spaces: \n \t and space. preprocessing flags #include : copy everything in the include files e.g. #include <iostreams> // system include files #inlcude Rectangle.h // user defined files #define: string substitution e.g. #define PI 3.1415926 #ifdef #endif e.g #ifdef DEBUG

avoid multiple inclusion of header files #ifndef #define #endif

Separating Class Definition and Class Implementation


Header (include) files extension: .h contain function headers for non-OOP coding (e.g. math.h) contain class definitions for OOP coding (e.g. iostreams.h) needed for the compiler to perform type checking distributed as text file with software libraries implementations are hided in .cpp files

Implementation files extension: .cpp contain function implementation for non-OOP coding contain class implementation for OOP coding compiled into .obj files obj files are binary files

Separating Class Definition and Class Implementation


Header file: Rectangle.h class Rectangle{ protected: int x, y; public: Rectangle (); Rectangle (int cx, int cy); double Area( ); }; Methods have only headers, no bodies

Separating Class Definition and Class Implementation


Implementation file: Rectangle.cpp #include "Rectangle.h" using namespace std; Rectangle::Rectangle () { x=0; y=0; } Rectangle::Rectangle (int cx, int cy) { x=cx; y=cy; }

double Rectangle::Area( ) { return x*y; }

Separating Class Definition and Class Implementation


Implementation file: Rectangle.cpp #include <iostream> // system header files #include Rectangle.h // user defined header files using namespace std; int main() { Rectangle rect1; cout << rect1.Area() << "\n"; cout << "Please enter 'q' to quit.\n "; char a; cin >> a; }

Preprocessing
#ifndef RECTANGLEH #define RECTANGLEH

class Rectangle{ protected: int x, y; public: Rectangle (); // only header, no body Rectangle (int cx, int cy); double Area( ); };
#endif

Compilation
cygwin pwd /cygdrive/c/Documents and Settings\xiao is mapped to C:\Documents and Settings\xiao mkdir oop copy main.cpp Rectangle.cpp and rectangle.h to the directory g++ main.cpp Rectangle.cpp I. o sep.exe ./sep Compilation flags: -I : search path for include files -o : output exe file name -l : add libraries files -c : generating object files -g : generating debugging info -D : defining symbolic constants -DDEBUG => #define DEBUG 1

Makefile
create a makefile with dependencies (C++Examples\MyRectangle) sep : main.o Rectangle.o MyRectangle.o g++ main.o Rectangle.o MyRectangle.o -o sep.exe

main.o : main.cpp g++ -c main.cpp


Rectangle.o : Rectangle.cpp g++ -c Rectangle.cpp MyRectangle.o : MyRectangle.cpp g++ -c MyRectangle.cpp in cygwin, type make make f makefile make will compare time stamps of the files and only recompile files being modified since last compilation. make will check the dependencies from top to bottom.

Command Line Arguments LINUX

Command Line Arguments


When running a program from the command line, you can pass arguments to the main function of the program. e.g.: mvcnc M1 V1 2 Each argument is passed as a null terminated string of characters to the main. e.g. M1 Argument strings are grouped together by an array of pointers to strings of characters: char * argv [] argc counts the total number of arguments passed, including the command name (e.g. mvcnc). If you need an integer, use atoi to convert a string to an integer. argc and argv are not object oriented. In Java and C#, they are merged into one as an array of String objects.

Example
int main(int argc, char* argv[]) { cout << "Your have typed: "; for(int i = 0; i < argc; i++) cout << argv[i] << " "; cout << "\n"; if(argc != 4) { cerr << "Usage: " << argv[0] << " Model View n(# of integer to process)." << endl; exit(1); } int n = atoi(argv[3]); cout << "You requested to process " << n << " integers. \n"; return(1); }

Command Line Arguments in Cygwin


Cygwin: a UNIX emulator for Windows. All programs->Cygwin->Cygwin Bash Shell cp T:/Xiao/OOP/C++/mvcnc.exe . (Use / instead of \ as separators in UNIX.) ./mvcnc ./mvcnc M1 V2 3

Command Line Arguments in V.S.


All programs->MS Visual Studio-> MS Visual Studio 2005 File->Open->Project/Solution Select the existing project In the Solution Explorer pane, click on the project name Right click to bring up the Property menu. Configuration Properties->Debugging->Command Arguments Type in the desired arguments. e.g. M1 V2 3 The arguments will be passed in when Debug->Run

Command Line Arguments in LINUX


What? UNIX, operating system for workstations, by Ken Thompson, Dennis Ritchie and Douglas McIlroy. http://en.wikipedia.org/wiki/Unix. LINUX, UNIX for PCs, Linus Torvalds, http://www.linux.org/ Fedoro, LINUX-based PC OS, http://fedoraproject.org/ Start LINUX in the labs: Reboot PC in the lab, hit return before Windows starts. GRUB, GRand Unified Bootloader, loads BIOs (Basic IO). Select Fedoro 2.6.21-1. User Name / Password

Command Line Arguments in LINUX


Use LINUX: Applications->System Tools->Terminal mkdir oop cd oop rm file-name rmdir directory-name Places->CD/DVD Creator Create, Compile and Run Programs Applications->Accessories->Text Editor Type you code and save it to mvcnc.cpp c++ mvcnc.cpp o mvcnc.exe (g++ mvcnc.cpp o mvcnc.exe) ./mvcnc M1 V2 3

Instantiating a Class in Java


ClassName ObjectName; Rectangle rect; declares a reference of class Rectangle. rect

A reference to a Rectangle object.

rect is the name of a memory space that stores a reference.


A reference is an internal pointer, it needs to point to an object before being used.

References in Java
Class Rectangle { protected: int x, y; Public: Rectangle () {x=0;y=0;} Public: Rectangle (int cx, int cy) {x=cx; y=cy;} Public: double area( ) { return x*y; } } int width 0

x y

Int height 0

Rectangle () {x=0;y=0;} w, int Rectangle (int cx, inth) cy) Area Area() double

References in Java and C#


Rectangle rect; double area = rect.Area(); // will not compile in Java Rectangle rect = new Rectangle (); // Use the first constructor rect 0x12345678 Dereferencing is automatic for a reference in Java. (No *rect) double area = rect.Area(); Please note the notation difference between a pointer and a name.

0x12345678 int width 0


x y

Int height 0

Rectangle () {x=0;y=0;} w, int Rectangle (int cx, inth) cy) Area Area() double

Value Types in Java and C++


int i; In both Java and C++: i is the name of a memory space that stores an integer value. int i = 8; i

i is a value type, for which we can directly store an integer value into the memory named as i. Compiler already allocated memory to store the value and we dont need to new to allocate memory to store the value.

Instantiating a Class in C++


Class Name; In C++: Rectangle rect; declares an object of class Rectangle. rect is a value type. rect

0 0

Rectangle () {x=0;y=0;}
Rectangle (int cx, int cy)

double Area()
rect is the name of a memory space that stores a Rectangle object.

Pointers in C++
Rectangle *rect; double area = rect->Area(); // Wrong! Compiles. Try! Rectangle *rect = new Rectangle (); // Correct, use the first constructor rect 0x12345678 double a = (*rect).Area(); double b = rect->Area();

0x12345678 int width 0

Int height 0
Rectangle () w, int Rectangle (int cx, inth) cy) Area Area() double
The type of a pointer tells the compiler the layout of the memory pointed to by the pointer. (Please note the notation difference between
a pointer and a name.)

Value Types v.s. Pointer/Reference Types


Variables of value types have the object (not the pointer/reference) memories allocated by the compiler and can be used as an object directly without new. Variables of pointer/reference types have the pointer/reference (not the object) memories allocated by the compiler and can not be used as an object directly without new. In Java and C#: Rectangle rect; // rect is a reference rect = new Rectangle (3, 4); // rect reference an object of allocated memory location double a = rect.Area(); // use . to dereference In C++: Rectangle *rect; // rect is a pointer rect = new Rectangle (3, 4); // rect points to an object of allocated memory location double a = (*rect).Area(); // use * and . to dereference double b = rect->Area(); // use -> to dereference In C++: Rectangle rect; // rect is a value type object of allocated memory location double a = rect.Area(); // use . to dereference

Value Types v.s. Pointer/Reference Types


Value Types are Stack Objects: memories allocated at compile time on the stack automatically freed when the objects are out of scope less overhead, code runs faster less flexible, sizes need to be known at compile time Pointer / Reference Types point to Heap Objects: memory are dynamically allocated at run time on the heap stays there even if the pointers/references are out of scope dynamically allocated memories need to be freed / deleted manually more flexible, sizes need not to be known at compile time more overhead, code runs slower

Free Dynamically Allocated Memory


In Java, dynamically allocated memories are automatically freed by the garbage collector. In C++, there is no garbage collector. dynamically allocated memories needs to be freed manually using free (C++ syntax) or delete (C syntax).
Rectangle *rect; // rect is a pointer rect = new Rectangle (1, 2); // rect points to an object of allocated memory location double a = rect->Area(); // use -> to dereference free(rect); // delete rect; rect = new Rectangle (3, 4); // rect points to another object of allocated memory location double a = rect->Area(); // use -> to dereference free(rect); // delete rect;

The Five+1 Nevers


1. 2. Never dereference pointers before allocating memories to them. Never dereference pointers before assigning values to the objects they point to. Dynamically allocated memories are not clean in C++. Dont forget to free the dynamically allocated memories after using them. This will cause memory leak. No one else will be able to use the memories allocated by your program before you free them. Never free the same memory more than once. Never free stack memory (used by value variables); C++ compilers allow you to make all of the above mistakes. Causing big problems for others that you even dont know. To avoid the problems, assign 0 to pointers when they are created and deleted. Only use the pointers when they are not equal to 0, i.e., if(pointer) is true. Rectangle *rect = 0; // rect is a pointer rect = new Rectangle (1, 2); // rect points to an object of allocated memory location if(rect) double a = rect->Area(); // use -> to dereference if(rect) free(rect); rect = 0; // free the memory and reset the pointer to 0;

3.
4. 5. 6. 7.

Code Example
Write down the output of the following code and draw a picture to show the memory structure. class Point { public: int x; int y; }; Point p1; p1.x = 1; p1.y = 2; Point p2 = p1; // Copies p1
cout << p1.x << << p1.y; cout << p2.x << << p2.y;

p2.x = 3; p2.y = 4;
cout << p1.x << << p1.y; cout << p2.x << << p2.y;

Point *p3; p3 = & p1;


cout << p1.x << << p1.y; cout << p3->x << << p3->y;

p3->x = 5; p3->y = 6;
cout << p1.x << << p1.y; cout << p3->x << << p3->y;

Code Example
Find and describe the errors in the following code. class Point { public: int x; int y; }; Point p1; p1.x = 1; p1.y = 2; Point *p3; cout << p3->x << << p3->y; p3 = & p1; cout << p3->x << << p3->y; delete p3; p3 = new Point(); cout << p3->x << << p3->y; delete p3; free (p3);

Code Example
Find and describe the errors in the following code. p3 = new Point(); p3->x = 3; p3->y = 4; Point *p4 = p3; cout << p4->x << << p4->y; delete p3; delete p4; Point *p5; int i = 1; if(i == 1) { Point p6; p5 = & p6; Point *p7 = new Point(); } cout << p5->x << << p5->y;

Arrays in C++
int a[2]; a[0] = 5; a[1] = 10; cout << a[0] << << a[1]; // stack objects, size has to be a constant and cant be changed at runtime. int size = 2; int b[size]; // will not compile in C++ // An array name represents a constant pointer, cant change its value. a

10

int size; cin >> size; // assuming user entered 2. int *p; // a pointer p = new int[size]; p[0] = 5; p[1] = 10; cout << p[0] << << p[1]; // heap objects; dynamically allocated at runtime, size can be a variable delete p; // free the memory. p

0xff

10

int *p2; // a pointer p2 = a; p2[0] = 50; p2[1] = 100; cout << a[0] << << a[1]; delete p2; // Dont do this.

Pointer Arithmetic
Pointers can be moved back and forth by one object with ++ and --

5
p

10

0xff00 0xff04
// a pointer

int a[2] = {5,10}; int *p; p = a; cout << p[0]; p++; cout << p[0]; p--; cout << p[0]; p++; cout << p[1];

Watch out where you are with a pointer!

TIC++V1:C15 Type Cast Virtual Function Polymorphism

Type Cast
class Rectangle{ protected: int x, y; public: Rectangle () {x=0;y=0;} Rectangle (int cx, int cy) {x=cx; y=cy;} double Area( ) { return x*y; } };

int width 0

x y

Rectangle rect;

Int height 0

Rectangle () {x=0;y=0;} w, int Rectangle (int cx, inth) cy) Area Area() double

Type Cast
class Rectangle{ protected: int x, y; public: Rectangle () {x=0;y=0;} Rectangle (int cx, int cy) {x=cx; y=cy;} double Area( ) { return x*y; } }; class MyRectangle: public Rectangle{ public: void Set(int dx, int dy){x=dx; y=dy;} };

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

double Area()
void Set(int dx, int dy)

MyRectangle rect2;

Down Cast : casting a pointer to a child class


Rectangle rect1; Rectangle *p1 = &rect1; p1 cout << p1->Area(); // ok p1->Set(1,1); // wont compile p2 rect1 0xff00 0xff00

MyRectangle *p2; // implicit cast to a child class, will not compile p2 = p1; //explicit cast to a child class, allowed p2 = (MyRectangle *) p1; cout << p2->Area(); // ok p2->Set(1,1); //will compile, cause runtime error

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

double Area()

Implicit type cast a pointer to its child class (down cast) is not permitted.
Explicit type cast a pointer to its child class (down cast) is permitted, but should be used with care.

Up Cast : casting a pointer to the parent class


MyRectangle rect2; MyRectangle *p2 = &rect2; p2 cout << p2->Area(); // ok p2->Set(1,1); // ok p1 Rectangle *p1; p1 = p2; // implicit cast to parent, ok //explicit cast to parent, ok p1 = (Rectangle *) p2; cout << p1->Area(); // ok p1->Set(1,1); // will not compile MyRectangle *p3; //explicit cast to child class, ok p3 = (MyRectangle *) p1; cout << p3->Area(); // ok p3->Set(1,1); // ok rect2 0xff00 0xff00

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

double Area()
void Set(int dx, int dy)

Implicit or explicit type cast a pointer to its parent class (up cast) is permitted. Up cast is important for using a predefined event loop. Shape->Draw(); Down cast should only be used when the original object is an instance of the child class.

Passing by Value
void Reset(MyRectangle rectf) { // rectf is the formal parameter, it has its own memory. rectf.Set(1,1); cout << rectf.Area(); // 1 } void main () { MyRectangle rect; cout << rect.Area(); // 0 Reset(rect); // rect is the actual parameter cout << rect.Area(); // 0 }

Pass-by-value: The value of the actual parameter is copied to the formal parameter when a method is called. The value of the formal parameter is not copied to the actual parameter when the method returns. The formal parameter expires when the method returns. The value of the actual object can not be changed by the called method.

Passing by Pointer
void Resetp(MyRectangle *rectp) { // rectp is the formal parameter, a pointer. rectp->Set(1,1); rectp 0xff00 cout << rectp->Area(); } void main () { MyRectangle rect; rect cout << rect.Area(); // 0 Resetp(&rect); // &rect is the actual parameter cout << rect.Area(); // 1 }

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

double Area()
void Set(int dx, int dy)

Pass-by-pointer: The address of the object is copied to the pointer formal parameter when a method is called. When the pointer is dereferenced the actual object (rect in the main) is accessed. The value of the actual object can be changed by the called method.

Reference
A reference is an alias of an object, it references the same memory of the object. void main () { MyRectangle rect; cout << rect.Area(); // 0 // declare and initialize a reference MyRectangle &rectr = rect; rect rectr

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

cout << rectr.Area(); // use the reference as the object }

double Area()
void Set(int dx, int dy)

Passing by Reference
Void Reset(MyRectangle &rectr) { rectf // rectr is the formal parameter, a reference. rectr.Set(1,1); cout << rectr.Area(); // 1 } void main () { MyRectangle rect; rect cout << rect.Area(); // 0 // rect is the actual parameter, its reference is passed. Reset(rect); cout << rect.Area(); // 1 }

Rectangle () {x=0;y=0;} Rectangle (int cx, int cy)

double Area()
void Set(int dx, int dy)

Pass-by-reference: The formal parameter of a method is a reference of the actual object (rect in the main), when accessing the formal parameter you are really accessing the actual object. Its value can be changes by the called method.

Calling a Function
Call by Value Calling Function Called Function Side Effect Reset(rect); Reset(MyRectangle rect) No Call by Pointer Reset(&rect); Reset(MyRectangle *rectp) Yes Call by Reference Reset(rect); Reset(MyRectangle &rectr) Yes

Function Pointers
A function name is a pointer. Taking the address of a function gives its address. Therefore: function-name == &function-name

For challenges and fun, try the examples at


http://www.cs.uakron.edu/~xiao/oop/fun-ptrs.html A function returning an int A function returning an int pointer A function prototype A function pointer to a function returning an int A function pointer to a function returning an int pointer An array of function pointers to functions returning ints An array of function pointers to functions returning int pointers A pointer to a function pointer to a function returning an int An array of pointers to function pointers to functions returning ints A pointer to a function pointer to a function returning an int pointer An array of pointers to function pointers to functions returning int pointers

Virtual Functions

Binding
Connecting a function call to a function body is called binding When binding is performed before the program is run (by the compiler and linker), its called early binding, static binding or compile-time binding. When binding occurs at runtime, based on the type of the object, it is called late binding, dynamic binding or runtime binding. The key words, virtual, causes late binding in C++. If a function is declared as virtual in the base class, it is virtual in all the derived classes

Late Binding in C++


The keyword virtual tells the compiler it should not perform early binding The compiler creates a single table (called the VTABLE) for each class that contains virtual functions. The compiler places the addresses of the virtual functions for that particular class in the VTABLE. In each class with virtual functions, it secretly places a pointer, called the vpointer (abbreviated as VPTR), which points to the VTABLE for that object. When you make a virtual function call through a base-class pointer (that is, when you make a polymorphic call), the compiler quietly inserts code to fetch the VPTR and look up the function address in the VTABLE, thus calling the correct function and causing late binding to take place.

Late Binding Example

Instrument.cpp: an Example of Late Binding and Polymorphism in C++

Four objects are newed at runtime: a Wind, a Percussion, a Stringed and a Brass. Their pointers are all upcasted into Instrument *. When executing the what functions, the correct what belonging to the classes, not the one in Instrument, are used. This is called polymorphism, since one type of function pointer, Instructment->what, actually points to different functions and therefore behaves differently at different situations. Polymorphism says which function to call is not determined by the type of the pointer but by the type of the objects its is pointed to. Polymorphism is achieved through late binding of those functions in the VTABLE. In C++, the virtual keyword causes late binding. Note Instrucment *ip behaves polymorphically too even though all the objects it points to are auto objects. Now remove virtual in front of what in Instrucment. What happends? Also note, there is no adjust function in Brass, so it is bound to the adjust in Wind.

CORBA
Common Object Request Broker Architecture http://www.omg.org/gettingstarted/corbafaq.htm A specification (standard) that allows object sharing over the network. Independent of computer, operating system, programming language, and network. Managed by OMG (Object Management Group) For each object type an interface is defined in OMG IDL (Interface Definition Language) The interface is independent of programming language, but maps to C, C++, Java, COBOL, Smalltalk, Ada, Lisp, Python, and IDLscript. CORBA 2 refers to CORBA interoperability and the IIOP protocol CORBA 3 refers to the CORBA Component Model CORBA/e refers to CORBA for embedded Less than 20 venters in total in 2007. http://corba-directory.omg.org/vendor/list.htm Web Service is a more promising alternative.

IIOP and GIOP


IIOP (Internet Inter-ORB Protocol) is the implementation of GIOP for TCP/IP General Inter-ORB Protocol (GIOP) is the abstract protocol for which object request brokers (ORBs) communicate through the network. Both specified by OMG. Three parts of GIOP: Common Data Representation (CDR) Interoperable Object Reference (IOR) The defined message formats Java CORBA Examples http://java.sun.com/developer/codesamples/idl.html Real-time CORBA examples http://www.omg.org/news/meetings/workshops/presentations/realtime_em b_presentations/Realtime_Tutorial_Slides/RTCORBA_workshop_examples.pdf

Anda mungkin juga menyukai