Sie sind auf Seite 1von 77

Satish kale C++ MANUAL C++ Notes

7.18.9. THE C++ I/O SYSTEM o 7.18.9.1. C++ I/O Basics o 7.18.9.2. Formatted I/O o 7.18.9.3. File I/O 7.18.10. CLASSES AND OBJECTS o 7.18.10.1. Classes and Objects o 7.18.10.2. Encapsulation and Information Hiding o 7.18.10.3. Constructors and Destructors 7.18.11. VARIABLE SCOPE AND LIFETIME o 7.18.11.1 Namespaces o 7.18.11.2 Variable Scope o 7.18.11.3 Variable Lifetime 7.18.12. FUNCTION OVERLOADING o 7.18.12.1. Polymorphism o 7.18.12.2. Ambiguity 7.18.13. OPERATOR OVERLOADING o 7.18.13.1. Operator Overloading Using a Member function o 7.18.13.2. Operator Overloading using a Friend Function o 7.18.13.3. Restrictions in Operator Overloading 7.18.14. INHERITANCE o 7.18.14.1. Base Classes and Derived Classes o 7.18.14.2. Member Access o 7.18.14.3. Multiple Inheritance and Inheriting Multiple Base classes 7.18.15. ARRAYS OF OBJECTS o 7.18.15.1 Arrays of Objects o 7.18.15.2. Initialization without Parameters o 7.18.15.3. Initialization with One Parameter o 7.18.15.4. Initialization with More than One Parameter 7.18.16. POINTERS TO OBJECTS o 7.18.16.1. Pointers to Objects o 7.18.16.2. Pointer Arithmetic
1

Satish

Satish kale C++ MANUAL 7.18.16.3. The 'this' Pointer o 7.18.16.4. Pointers to Classes Members 7.18.17. REFERENCES o 7.18.17.1. Pass Argument by Value o 7.18.17.2. Pass Argument by References o 7.18.17.3. Reference Arguments 7.18.18. VIRTUAL FUNCTIONS o 7.18.18.1. Polymorphic Classes and Virtual Functions o 7.18.18.2. Virtual Function Invocation o 7.18.18.3. Pure Virtual Functions and Abstract Classes 7.18.19. TEMPLATES o 7.18.19.1. Generic Functions o 7.18.19.2. Generic Classes o 7.18.19.3. Examples with More than One Generic Data Types 7.18.20. EXCEPTIONS o 7.18.20.1.The throw Statement o 7.18.20.2 The try Statement o 7.18.20.3 Caught all Exceptions o 7.18.20.4 Restricting Exceptions o 7.18.29.5 Rethrowing an Exception
o

7.18 C/C++ (Part 2) C++ was first invented by Bjarne Stroustrup in 1980 at Bell Laboratories in Murray Hill, New Jersey. He initially called it "C with Classes." However, in 1983 the name was changed to C++. C+ + is a superset of C. As a popular programming language, C has many excellent features. However, once a program exceeds 25,000 to 100,000 lines of code, it becomes too difficult to be comprehended as a whole. The purpose of C++ is to overcome this limit and provide a better way to manage larger, more complex programs, by using object oriented programming (OOP).

Satish

Satish kale C++ MANUAL 7.18.9. THE C++ I/O SYSTEM 7.18.9.1. C++ I/O Basics When a C++ program is running, the following four built-in streams are automatically opened: Stream cin cout cerr clog Meaning Default Device keyboard screen Corresponding C stream stdin stdout stderr

standard input standard output standard error screen output buffered version of screen cerr

The following is an example of using simple I/O streams: Example / ******************************************** ************* * * FILE NAME: basics.cpp * * AUTHOR: Zhiwei Wang * * DATE: May. 1997 * * DESCRIPTION: An example for simple I/O stream * ******************************************** ***************/ #include <iostream> using namespace std;

Satish

Satish kale C++ MANUAL main(){ char name[50]; cout << "Please enter your name: "; cin >> name; cout << "Hello, " << name << ".\n"; cout << "My name is Zhiwei." << endl; // 'endl' can be used in place of "\n" return 0; } // End of program //****************************************** ***************** 7.18.9.2. Formatted I/O There are three member functions defined by ios that set the format parameters, namely: int width(int w); This function sets the field width. Here w is the field width. The returned value is the previous width. If a value uses less than the specified width, the field will be padded with fill character. The default fill character is space. int precision(int p); This function sets precision to p. The returned value is the previous precision. Precision determines the number of digits to be displayed after the decimal point. The default precision is 6. char fill(char ch); This function sets the fill character to ch. The previous fill character is returned. Here is an example that illustrates these functions / ******************************************** *******************

Satish

Satish kale C++ MANUAL FILE NAME: example1.cpp AUTHOR: Zhiwei Wang DATE: May 1998 DESCRIPTION: An example demonstrating how to use the width(), precision(), and fill() functions. ******************************************** *********************/ #include <iostream> using namespace std; main() { double pi = 3.1415926535; cout << pi << endl; cout.precision(3); cout << pi << endl; cout.precision(3); cout.width(10); cout << pi << endl; cout.precision(3); cout.width(10); cout.fill('0'); cout << pi << endl; return 0; } /* Output: mercury[105]% a.out

Satish

Satish kale C++ MANUAL 3.14159 3.14 3.14 0000003.14 */ Another way to perform formatted I/O is using manipulators. Manipulators are special functions that can be used to format i/o. In the previous example, 'endl' is a manipulator to output a newline character and flush the stream. Some manipulators require parameters. To access manipulators that take parameters, you have to include <iomanip.h> in your program. The following is an example of using manipulators to format the output. / ******************************************** ********************* FILE NAME: example2.cpp AUTHOR: Zhiwei Wang DATE: May. 1998 DESCRIPTION: An example demonstrating how to use the manipulators. ******************************************** *********************/ #include <iostream> #include <iomanip> using namespace std; main() { int i=100; double pi = 3.1415926535;

Satish

Satish kale C++ MANUAL cout << i << endl; cout << hex << i << endl; cout << pi << endl; cout << setfill('0') << setw(10) << setprecision(3) << pi << endl; } return 0;

/* Output: 100 64 3.14159 0000003.14 */ 7.18.9.3. File I/O To perform file I/O, you must include the header file <fstream>. It defines the classes ifstream, ofstream, and fstream, which are needed to open files. stream name stream type Ifstream Input Ofstream output Fstream input and output To open a file, you create a stream and then call the member function open(). Example:

Satish

Satish kale C++ MANUAL / ******************************************** *************** * FILE NAME: readfile.cpp * * AUTHOR: Zhiwei Wang * * DATE: May. 1997 * * DESCRIPTION: An example for simple disk file I/O * ******************************************** ****************/ #include <iostream> #include <fstream> #include <string.h> using namespace std; main(){ ifstream in; char filename[20]; cout << "Enter the file name to read from: "; cin >> filename; in.open(filename); if (!in) { cout << "Input file cannot be opened.\n"; return(1); } char str[80]; while (!in.eof()) { in >> str; cout << str << " "; strcpy(str, ""); } cout << "\n"; in.close(); return (0);

Satish

Satish kale C++ MANUAL } //END OF PROGRAM //****************************************** ******************/ 7.18.10. CLASSES AND OBJECTS 7.18.10.1. Classes and Objects In C++, the class forms the basis of object-oriented programming. It is the basic unit of encapsulation. Classes define the nature of objects. To create a class, use the key word class. Here is the syntax: class class_name { private data and functions access_specifier: data and functions access_specifier: data and functions access_specifier: data and functions . . . access_specifier: data and functions } object_list; Example 1 class vector { public: float x, y; };

Satish

Satish kale C++ MANUAL In this example, we define a class named vector The vector class has two data members: x and y that are float numbers. Both x and y are public, which means they are accessible to other parts of the program. A class name can be used as a type to declare objects. An object is a instance of a class. The following declares three objects a, b, and c instances of the vector class: vector a, b, c; Let us examine a complete program to make the preceding explanation clearer. Example / ******************************************** ************* Filename: sum.cpp Date: April 4, 1997 Author: Zhiwei Wang Student Number: Description: This program calculates the sum of two vectors. ******************************************** **************/ #include <iostream> using namespace std; class vector { public: int x, y; }; specifier specific code as

Satish

10

Satish kale C++ MANUAL main(){ vector a, b, c; a.x = 15; a.y = 20; b.x = 100; b.y = 40; c.x = a.x + b.x; c.y = a.y + b.y; cout<< "The x-coordinate of vector c is: "<< c.x<<"\n"; cout<< "The y-coordinate of vector c is: "<< c.y<<"\n"; return 0; } //Output: //The x-coordinate of vector c is: 115 //The y-coordinate of vector c is: 420 // End of Program //****************************************** **************************

7.18.10.2. Encapsulation and Information Hiding Information hiding refers to the control of access levels of members of a class. This is done by using the three access_specifiers: public, private, and protected. A class member specified as 'public' is accessible from outside the class, while a 'private'

Satish

11

Satish kale C++ MANUAL member can be accessed only by other members of the same class, or a friend function. 'Protected' specifier is similar to 'private' as long as derived classes are not involved. We will discuss 'friend functions' and 'Derived classes' later. Example: / ******************************************** **************** Filename: classes.cpp Author: Zhiwei Wang Date: May, 1997 Description: A simple class example ******************************************** ****************/ #include <iostream> using namespace std; class person { // A simple class int hour; int rate; public: int income(void); // with two methods void initialize(int, int); }; int person::income(void) //Income of a person { return hour * rate; }

Satish

12

Satish kale C++ MANUAL void person::initialize(int init_hour, int init_rate) { hour = init_hour; rate = init_rate; } main(){ person a, b; a.initialize(12, 10); b.initialize(8, 8); cout << "The income of person a is " << a.income() << "\n"; cout << "The income of person b is " << b.income() << "\n"; return 0; } // End of Program //****************************************** ****

7.18.10.3. Constructors and Destructors A function declared inside a class is a member function. Member functions have full access to all members of the class. A constructor is a special member function which has the same name as the class. Constructors are used to initialize the class and are automatically called when the objects are created. The complement of the constructor is the destructor. A destructor name begins with a tilde (~) character

Satish

13

Satish kale C++ MANUAL followed by the name of the class. When an object is destroyed, its destructor is automatically called. Destructors are needed because in many cases, some actions should be taken when an abject is destroyed. For example, memory spaces need to be freed, or an opened file need to be closed. Neither constructor nor destructor can return any value, so there is no return type specified for them. Example: / ******************************************** **************** Filename: structor.cpp Author: Zhiwei Wang Date: May, 1997 Description: A simple class example with constructor and destructor. ******************************************** ****************/ #include <iostream> using namespace std; class person { // A simple class int hour; int rate; public: person(void); ~person(void); int income(void); // with two methods void initialize(int, int);

Satish

14

Satish kale C++ MANUAL }; person:: person(void) { hour = 40; rate = 15; } person::~person(void) { hour = 0; rate = 0; cout << "Personal information deleted.\n"; } int person::income(void) //Income of a person { return hour * rate; } void person::initialize(int init_hour, int init_rate) { hour = init_hour; rate = init_rate; } main(){ person a, b; cout << "The income of a.income() << "\n"; cout << "The income of b.income() << "\n"; a.initialize(12, 10); b.initialize(8, 8); cout << "The income of a.income() << "\n"; cout << "The income of b.income() << "\n";

person a is " << person b is " <<

person a is " << person b is " <<

Satish

15

Satish kale C++ MANUAL return 0; } /* output: The income of person a is 600 The income of person b is 600 The income of person a is 120 The income of person b is 64 Personal information deleted. Personal information deleted. */ // End of Program //****************************************** ******************

7.18.11. Variable Scope and Lifetime 7.18.11.1. Namespaces A namespace is a mechanism by which the program can create a named scope. A namespace definition consists of the word namespace, then an identifier, and the the body of the namespace. Example: // in header file cstdlib: namespace std { ... int abs(int);

Satish

16

Satish kale C++ MANUAL ... } Identifiers declared within the namespace body are said to have namespce scope. They cannot be accessed outside the body except by using one of the following methods: 1. using the name of the namespace, the scope resolution operator, and the indentifier. int a, b; a = std::abs(b); 2. using the 'using declaration' using std::abs; 3. using a 'using directive' using namespace std; Example: // Filename: hiusingname.cpp #include <iostream> using namespace std; main() { cout << "Hi" << endl; } Notice that in the preprocessor directive "#include <iostream>", the header file doesn't have the suffix .h. After the "#include", a using directive follows. When you compile this

Satish

17

Satish kale C++ MANUAL program (hiusingname.cpp) in hercules, you need to use the "LANG' option: hercules[1]% CC hiusingname.cpp -LANG:std If you use the older header file <iostream.h>, you don't need the using directive: Example: // filename: hi.cpp #include <iostream.h> main() { cout << "Hi" << endl; } When you compile this program (hi.cpp), you don't need to use the "LANG" option: hercules[1]% CC hi.cpp 7.18.11.2. Variable Scope Scope refers to the region of program code where it is legal to reference an identifier. Class scope: The scope of class members is within the classe (struct, union) local: The scope of an dentifiers declared inside a block starts from the point of the declaration and ends at the end of the block. namespace scope: The scope of identifiers declared inside a namespace is within the namespace.

Satish

18

Satish kale C++ MANUAL global scope: The scope of an identifier declared outside all functions and classes have the global scope. Example: #include <iostream> using namespace std; int num = 0; // global num

namespace myNamespace { int num = 1; // num in a namespace } void myFunction(int num); void myFunction2(); void myFunction3(); void main() { cout << num << endl; // global num 0 int num = 3; myFunction3(); // 0 cout << num << endl; // 3 cout << myNamespace::num << endl; // 1 myFunction2(); // 4 myFunction(num); // 9 } // out put: 0 0 3 1 4 9 in each line void myFunction(int num) { num = 9; cout << num << endl; }

Satish

19

Satish kale C++ MANUAL void myFunction3() { cout << num << endl; } void myFunction2() { int num = 4; cout << num << endl; } 7.18.11.3. Lifetime of a Variable The lifetime of a variable refers to the period of time during program execution when an identifier actually has memory allocated to it. An automatic variable is one whose storage is allocated at the block entry and deallocated at the block exit. A static variable is one whose storage remains allocated for the duration of the entire program. All global variables are static variables. By default, variables declared within a block are automatic variables. However, you can use 'static' to declare a static local variable. Static class members If you declare a static variable in a class, all objects will share the same variable. Example: #include <iostream> using namespace std; class myClass { public:

Satish

20

Satish kale C++ MANUAL static int share; int num; // class

};

int myClass::share; void main() { myClass o1, o2; o1.share = 1; o1.num = 1; cout << o1.share << endl; cout << o1.num << endl; o2.share = 2; o2.num = 2; cout << o2.share << endl; cout << o2.num << endl; cout << o1.share << endl; cout << o1.num << endl;

Member functions may also be declared as static. There are several restrictions placed onstatic member functions: They may only access other static members of the class. static member functions do not have a 'this' pointer. There cannot be a static and a non-static version of the same function. Example #include <iostream> using namespace std; class myClass {

Satish

21

Satish kale C++ MANUAL static int share; int num; public: static int getShare() {return share;} int getNum() {return num;} static void setShare(int a) { share = a; void setNum(int a) { num = a;}

} };

int myClass::share; void main() { myClass o1; o1.setShare(1); o1.setNum(1); cout << o1.getShare() << endl; cout << o1.getNum() << endl; myClass::setShare(2); cout << o1.getShare() << endl; cout << o1.getNum() << endl; }

7.18.12. FUNCTION OVERLOADING 7.18.12.1. Polymorphism In C++, you can use the same name for two or more functions, providing that the number of parameters or the data type of parameters are different. This is called function overloading. Function overloading is one way to realize polymorphism, which means to

Satish

22

Satish kale C++ MANUAL allow one interface to be used with multiple methods. Example / ******************************************** *************** Filename: overload.cpp Author: Zhiwei Wang Date: July, 1997 Description: A simple example of function overloading ******************************************** ****************/ #include <iostream> using namespace std; int f(float); // This function triples a float and returns int int f(int); // This function returns the same integer float f(float, float); // This function averages two floats main() { int num = 12; float num2 =12.0; cout << "The number is " << f(num) << "\n"; cout << "3 times 12 is " << f(num2) << "\n"; cout << "The average of 12 and 36 is " << f(12.0, 36.0) << "\n"; return 0; }

Satish

23

Satish kale C++ MANUAL int f(int in_value) // This returns the same value { return in_value; } int f(float in_value) // Triples a float & return int { return (int)(3.0 * in_value); } float f(float in1, float in2) // This averages two floats { return (in1 + in2)/2.0; } /* Output: The number is 12 3 times 12 is 36 The average of 12 and 36 is 24 */ // End of Program //****************************************** ******* The output of the previous program shows that the C++ compiler knows which function should be invoked by analyzing the parameter lists. 7.18.12.2. Ambiguity C++ has a feature called 'automatic type conversion', which means C++ will automatically attempt to convert the

Satish

24

Satish kale C++ MANUAL arguments used to call a function into the data type expected by the function. In some situation, this makes the compiler unable to choose between different overloaded functions. This situation is said to be ambiguous. Let us make a small change in the program overload.cpp'. Instead of calling function 'f()' using the variables 'num' and 'num2', we use their values directly. i.e. we replace the lines int num = 12; float num2 =12.0; cout << "The number is " << f(num) << "\n"; cout << "3 times 12 is " << f(num2) << "\n"; with cout << "The number is " << f(12) << "\n"; cout << "3 times 12 is " << f(12.0) << "\n"; Compile the altered program and you will get the following: mercury[208]% CC example2.cpp "example2.cpp", line 16: error(3389): more than one instance of overloaded function "f" matches the argument list: function "f(float)" function "f(int)" cout << "3 times 12 is " << f(12.0) << "\n"; error detected in the compilation of "example2.cpp". mercury[209]% 7.18.13. OPERATOR OVERLOADING

Satish

25

Satish kale C++ MANUAL 7.18.13.1. Operator Overloading Using a Member function Many operators can be overloaded by creating operator functions. Operator functions can be either members or non members of the class that the operator will operate on. The format to create a member operator function is: ret-type class-name::operator#(arg-list) { // operation definition } where ret-type is the data type of the object returned by the operator. The # is a placeholder which will be replaced by the symbol of the operator. If you are overloading a unary operator, arg-list will be empty, if you are overloading a binary operator, arg-list will have one parameter, etc. Let us define a vector class and overload the + operator: Example / ******************************************** **************** Filename: opover.cpp Author: Zhiwei Wang Date: July, 1997 Description: overload operators using member functions. ******************************************** ****************/ #include <iostream>

Satish

26

Satish kale C++ MANUAL using namespace std; class vector { float x, y; public: vector(){}; vector(float a, float b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} vector operator+(vector v); float operator*(vector v); }; vector vector::operator+(vector v) { vector temp; temp.x = v.x + x; temp.y = v.y + y; return temp; } float vector::operator*(vector v) { return (v.x * x + v.y * y); } main() { vector f1(19, 97), f2(7, 11); cout << "vector 1 is: "; f1.display(); cout << "vector 2 is: "; f2.display(); cout << "The sum of the two vectors is: "; (f1+f2).display(); cout << "The inner product of the two vectors is: " << f1 * f2 << endl; return 0;

Satish

27

Satish kale C++ MANUAL } /* The output of the program is: vector 1 is: x=19, y=97 vector 2 is: x=7, y=11 The sum of the two vector is: x=26, y=108 The inner product of the two vector is: 1200 */ // End of Program //****************************************** ****** Note that the overloaded '+' operator returns a vector, this makes the statement (f1+f2).display(); possible. 7.18.13.2. Operator Overloading using a Friend Function Operators can be overloaded using friend functions. When use a friend function to overload a unary operator, the function has one parameter; to overload a binary operator, two parameters; etc. The following program rewrites the preceding example using friends to overload operators. Note that the main() function does not change. / ******************************************** **************** Filename: opover2.cpp

Satish

28

Satish kale C++ MANUAL Author: Zhiwei Wang Date: July, 1997 Description: overload operators using friend functions ******************************************** ****************/ #include <iostream> using namespace std; class vector { float x, y; public: vector(){}; vector(float a, float b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} friend vector operator+(vector v1, vector v2); friend float operator*(vector v1, vector v2); }; vector operator+(vector v1, vector v2) { vector temp; temp.x = v1.x + v2.x; temp.y = v1.y + v2.y; return temp; } float operator*(vector v1, vector v2) { return (v1.x * v2.x + v1.y * v2.y); } main() { vector f1(19, 97), f2(7, 11);

Satish

29

Satish kale C++ MANUAL cout << "vector 1 is: "; f1.display(); cout << "vector 2 is: "; f2.display(); cout << "The sum of the 2 vectors is: "; (f1+f2).display(); cout << "The inner product of the two vector is: " << f1 * f2 << endl; return 0; } // End of Program //****************************************** ***** 7.18.13.3. Restrictions in Operator Overloading Technically one can define any activities inside an operator function. The short program gives an example. / ******************************************** **************** Filename: unexpected.cpp Author: Zhiwei Wang Date: July, 1997 Description: ******************************************** ****************/ #include <iostream> using namespace std; class vector { float x, y;

Satish

30

Satish kale C++ MANUAL public: vector(){}; vector(float a, float b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} vector operator+(vector v); }; vector vector::operator+(vector v) { cout << "This is a weird addition, isn't it?\n"; return v; } main() { vector f1(19, 97), f2(7, 11); f1 + f2; return 0; } /* Output: This is a weird addition, isn't it? */ // End of Program //****************************************** ******* It is suggested that when you overload an operator, you have sufficient reason to do so. There are some restrictions that apply to operation overloading.

You cannot alter the precedence of the operator;


31

Satish

Satish kale C++ MANUAL


You cannot change the number of operands of the operator; The operators list below cannot be overloaded: . :: .* ?

7.18.14. INHERITANCE 7.18.14.1. Base Classes and Derived Classes Inheritance is one of the cornerstones of object-oriented programming. It allows the members of one class to be used as if they were members of a second class. Using inheritance, you create a base class that defines members common to a set of classes, and then create derived classes to inherit the base class. The members of the base class will become the members of the derived classes. Let us examine an example: Example / ******************************************** **************** Filename: 2d3d.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program demonstrates how a derived class (measure_3d) inherits the base class (measure_2d).

Satish

32

Satish kale C++ MANUAL ******************************************** ****************/ #include <iostream> using namespace std; // base class definition class measure_2d { protected: int length, width; public: void set (int a, int b) {length=a; width=b;} void display() { cout << "length=" << length << "\nwidth=" << width << "\n";} int area() { return length*width;} }; // derived class definition class measure_3d : public measure_2d { int height; public: measure_3d (int a) {height=a;} void display_height() { cout << "height=" << height << "\n";} int volume() { return length * width * height;} }; main(){ measure_3d box(6); // access members of base class box.set(2, 4); box.display(); cout << "The area occupied by the box is " << box.area() << "\n";

Satish

33

Satish kale C++ MANUAL // access members of derived class box.display_height(); cout << "The volume of the box is " << box.volume() << "\n"; return 0; } /* Output: length=2 width=4 The area occupied by the box is 8 height=6 The volume of the box is 48 */ // End of Program //****************************************** ******* 7.18.14.2. member Access As we have seen in the example, the general form to define a class to inherit base class is: class derived-class-name:access base-classname { // body of class }; where 'access' is the base class access specifier, which should be either public, private, or protected. If no access specifier is explicitly presented, the default one will be assumed. If the derived class is a class, the default access specifier is private, If the derived class is struct, it is public.

Satish

34

Satish kale C++ MANUAL Let us examine what happens when the access specifier is public, private, or protected respectively. When the specifier is public, all public members of the base class become public members of the derived class, all protected members of the base class become protected members of the derived class, but all private members remain private to the base class and are not accessible by the members of the derived class. Let us comment out the keyword 'protected' in the definition of class measure_2d in the previous program '2d3d.cpp'. By default, 'length' and 'width' will be private to the base class measure_2d. The new program is as below: Example / ******************************************** **************** Filename: 2d3d_a.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program demonstrates how a derived class (measure_3d) inherits the base class (measure_2d). ******************************************** ****************/ #include <iostream> using namespace std; // base class definition

Satish

35

Satish kale C++ MANUAL class measure_2d { // protected: int length, width; // length and width are private now by default public: void set (int a, int b) {length=a; width=b;} void display() { cout << "length=" << length << "\nwidth=" << width << "\n";} int area() { return length*width;} }; // derived class definition class measure_3d : public measure_2d { int height; public: measure_3d (int a) {height=a;} void display_height() { cout << "height=" << height << "\n";} int volume() { return length * width * height;} // error here: length and width is private to the base // class and cannot be access here by a member of the // derived class. }; main(){ measure_3d box(6); // access members of base class box.set(2, 4); box.display(); cout << "The area occupied by the box is " << box.area() << "\n"; // access members of derived class

Satish

36

Satish kale C++ MANUAL box.display_height(); cout << "The volume of the box is " << box.volume() << "\n"; return 0; } Compiling the altered program .cpp, you will get: mercury[13]% CC 2d3d_a.cpp "2d3d_a.cpp", line 24: error(3346): member "measure_2d::length" is inaccessible int volume() { return length * width * height;} ^ "2d3d_a.cpp", line 24: error(3346): member "measure_2d::width" is inaccessible int volume() { return length * width * height;} ^ 2 errors detected in the compilation of "2d3d_a.cpp". When the access specifier is private, all public and protected members of the base class become private members of the derived class. For example, let us keep everything in '2d3d.cpp' unchanged, except replacing the process specifier 'public' with 'private'. The new program is as below: / ******************************************** **************** Filename: 2d3d.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program demonstrates how a derived class (measure_3d) inherits the base class (measure_2d).

Satish

37

Satish kale C++ MANUAL ******************************************** ****************/ #include <iostream> using namespace std; // base class definition class measure_2d { protected: int length, width; public: void set (int a, int b) {length=a; width=b;} void display() { cout << "length=" << length << "\nwidth=" << width << "\n";} int area() { return length*width;} }; // derived class definition class measure_3d : private measure_2d { int height; public: measure_3d (int a) {height=a;} void display_height() { cout << "height=" << height << "\n";} int volume() { return length * width * height;} }; main(){ measure_3d box(6); // error: cannot access members of base class box.set(2, 4); box.display();

Satish

38

Satish kale C++ MANUAL cout << "The area occupied by the box is " << box.area() << "\n"; // access members of derived class box.display_height(); cout << "The volume of the box is " << box.volume() << "\n"; return 0; } // End of Program //****************************************** ********** The following is what we get when we compile the altered program: mercury[18]% CC 2d3d_b.cpp "2d3d_b.cpp", line 31: error(3346): function "measure_2d::set" is inaccessible box.set(2, 4); ^ "2d3d_b.cpp", line 32: error(3346): function "measure_2d::display" is inaccessible box.display(); ^ "2d3d_b.cpp", line 33: error(3346): function "measure_2d::area" is inaccessible cout << "The area of the box is " << box.area() << "\n"; ^ 3 errors detected in the compilation of "2d3d_b.cpp". When the access specifier is 'protected', all public and protected members of the base class become protected members of the derived class. Protected members are similar to private members in that they are not accessible to other non-members, but are different from private members when they are inherited: if the base class is

Satish

39

Satish kale C++ MANUAL inherited as protected or public, all protected members of the base class become protected members of the derived class. 7.18.14.3. Multiple Inheritance and Inheriting Multiple Base classes A derived class can be used as a base class for another derived class, this is referred to as multiple inheritance. A class can inherit more than one classes, this is called inheriting multiple base classes. In the following program, class 'measure_2d' inherits 'measure_l' and 'measure_w', this is an example of inheriting multiple base classes; class 'measure_3d' inherits 'measure_2d', while 'measure_2d' itself is a derived class, this is an example of multiple inheritance. / ******************************************** **************** Filename: m_inherit.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program gives examples of multiple inheritance and inheriting multiple classes. demonstrates how a derived class ******************************************** ****************/ #include <iostream> using namespace std; class measure_l { // base class protected: int length; public: void displayl() { cout << "length=" << length << "\n";}

Satish

40

Satish kale C++ MANUAL }; class measure_w { // base class protected: int width; public: void displayw() { cout << "width=" << width << "\n";} }; // measure_2d inherits two classes, an example of inheriting // multiple classes class measure_2d: public measure_l, public measure_w { public: void set (int a, int b) {length=a; width=b;} void display() { cout << "length=" << length << "\nwidth=" << width << "\n";} int area() { return length*width;} }; // measure_3d inherits a derived class, an example of // multiple inheritance class measure_3d : public measure_2d { int height; public: measure_3d (int a) {height=a;} void display_height() { cout << "height=" << height << "\n";} int volume() { return length * width * height;}

Satish

41

Satish kale C++ MANUAL }; main(){ measure_3d box(6); box.set(2, 4); box.display(); cout << "The area of the box is " << box.area() << "\n"; box.display_height(); cout << "The volume of the box is " << box.volume() << "\n"; return 0; } // End of Program //****************************************** ********* 7.18.15. ARRAYS OF OBJECTS 7.18.15.1 Arrays of Objects An array is a collection of variables of the same data type. Its elements are referenced by the name of the array followed by a pair of square brackets with an index number in them. For example, the following statement declares an array of 100 integers. int my_array[100]; The syntax for declaring an object array is the same as it is for any other data types, except that the forms to initialize an array are different according to how many parameters required by the constructor function. 7.18.15.2. Initialization without Parameters The following example declares an array of object 'vector_1'.

Satish

42

Satish kale C++ MANUAL / ******************************************** ************* Filename: vector1.cpp Description: ******************************************** **************/ #include <iostream> using namespace std; class Vector_1 { int x; public: void set_x(int num) {x=num;} int get_x() {return x;} }; main(){ Vector_1 my_array[4]; my_array[0].set_x(1); my_array[1].set_x(9); my_array[2].set_x(9); my_array[3].set_x(7); for (int i=0; i<4; i++) { cout << my_array[i].get_x() << endl; } return 0; } // End of Program //****************************************** ********** 7.18.15.3. Initialization with One Parameter

Satish

43

Satish kale C++ MANUAL The following example is similar to the previous one but this time class vector_1 has a constructor function which requires one parameter. In this case, the array can be initialized by using a list of arameters. / ******************************************** ************* Filename: vector1.cpp Description: ******************************************** **************/ #include <iostream> using namespace std; class Vector_1 { int x; public: Vector_1 (int num) {x=num;} // constructor can not return a value. int get_x() {return x;} }; main(){ Vector_1 my_array[4] = {1, 9, 9, 7}; for (int i=0; i<4; i++) { cout << my_array[i].get_x(); } cout << endl; return 0; } // End of Program //****************************************** **********

Satish

44

Satish kale C++ MANUAL 7.18.15.4. Initialization with More than One Parameter The following example illustrates how to initialize an array of objects when the constuctor requires more than one parameters. / ******************************************** ************* Filename: vector2.cpp Date: July 24, 1997 Author: Zhiwei Wang Student Number: Description: Declaring an array of objects. ******************************************** **************/ #include <iostream> using namespace std; class Vector_2 { int x, y; public: Vector_2 (int num1, int num2) {x=num1; y=num2;} int get_x() {return x;} int get_y() {return y;} }; main(){ Vector_2 my_array[2] = {vector_2(1, 9), vector_2(9, 7)}; for (int i=0; i<2; i++) { cout << my_array[i].get_x() << my_array[i].get_y(); }

Satish

45

Satish kale C++ MANUAL cout << endl; return 0;

} // End of Program //****************************************** **********

7.18.16. POINTERS TO OBJECTS 7.18.16.1. Pointers to Objects The syntax to declare a pointer to an object is the same as that to declare a pointer to any other data types. Here is an example: Example: / ******************************************** **************** Filename: pointer1.cpp Author: Zhiwei Wang Date: July, 1997 Description: An example illustrating how to declare a pointer to object, and how to assign the address of an object to the pointer. ******************************************** ****************/ #include <iostream> using namespace std; class vector {

Satish

46

Satish kale C++ MANUAL int x, y; public: vector(){}; vector(int a, int b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} }; main(){ vector *p; // p is a pointer to vector vector f1(19, 97), f2(7, 12); p = &f1; // assigning the address of f1 to p cout << "vector 1 is: "; p->display(); // using an arrow to access the member function cout << "vector 2 is: "; f2.display(); return 0; } In the preceding example, 'p' is a pointer to 'vector'. When you use a pointer (e.g. 'p') to access a member function, you use the arrow operator instead of a dot. 7.18.16.2. Pointer Arithmetic Addition and substraction can be applied to pointers. When you declare an array of objects, the objects are stored in contiguous memory locations. If a pointer p is assigned the address of an array, then p points to the first item of the array, p+1 points to the second item, p+2 points to the third item, etc. 7.18.16.3. The 'this' Pointer Every member function of an object has an implicit argument called this that is a pointer to the object. You can use the this pointer

Satish

47

Satish kale C++ MANUAL to refer to the object itself. This is especially useful when you overload an operator. Example: / ******************************************** **************** Filename: this.cpp Author: Zhiwei Wang Date: July, 1997 Description: An example showing how to use the 'this' pointer to refer to the calling object. ******************************************** ****************/ #include <iostream> using namespace std; class vector { int x, y; public: vector(){}; vector(int a, int b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} vector operator++(); }; vector vector::operator++() { x++; y++; return *this;

Satish

48

Satish kale C++ MANUAL } main(){ vector f1(19, 97); cout << "vector 1 is: "; f1.display(); ++f1; cout << "After increment, it is: "; f1.display(); return 0; } // End of Program 7.18.16.4. Pointers to Classes Members C++ has a special type of pointer called 'a pointer to a class member'. A pointer to a class member provides an offset into an object at which the member can be found. Since a point to a class member is not a true pointer in the normal sense, to access a member, you use the special operators .* and ->* instead of using the operators . and ->. When declaring pointers to members, you must specify the class and use the scope operator. The following is an example. Please pay attention to the syntax of each declaration. / ******************************************** **************** Filename: member.cpp Author: Zhiwei Wang Date: July, 1997 Description: An example of using pointers to class members.

Satish

49

Satish kale C++ MANUAL ******************************************** ****************/ #include <iostream> using namespace std; class vector { public: int x, y; vector(){}; vector(int a, int b) {x=a; y=b;} void display() {cout << "x=" << x << ", y=" << y << endl;} }; main(){ int vector::*d; // d is a pointer to data member. void (vector::*f)(); // f is a pointer to function member. vector f1(19, 97), f2(7, 12); vector *p; // p is a normal pointer to object. p = &f2; // assign the address of f2. d = &vector::x; // get offset of x. f = &vector::display; // get offset of display(). // access data member. cout << "The first value of f1 is " << f1.*d << endl; // access function member. (f1.*f)(); // access data member via pointer 'p'. cout << "The first value of f2 is " << p>*d << endl;

Satish

50

Satish kale C++ MANUAL // access function member via pointer 'p'. (p->*f)(); return 0; } // End of Program 7.18.17. REFERENCES In C, there are two ways to pass arguments to a function: 'call by value' and 'call by references'. C++ has a feature to do 'call by reference' automatically. 7.18.17.1. Pass Argument by Value In general, when an argument is passed to a function, the value of the argument is copied to the 'formal parameter'. Any changes to the formal parameter has no effect on the argument. This is called 'pass by value'. The following program illustrates this. It attempts in vain to swap the value of two variables. / ******************************************** **************** Filename: swap1.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program illustrates that 'call by value' will not change the value of the original arguments ******************************************** ****************/ #include <iostream> using namespace std; void swap(int i, int j);

Satish

51

Satish kale C++ MANUAL main(){ int a = 1, b = 2; cout << " a = " << a << "\tb = " << b << endl; swap(a, b); cout << "After wrong swap:\n"; // The value WILL NOT be changed. cout << " a = " << a << "\tb= " << b << endl; return 0; } void swap(int i, int j){ int temp; temp = i; i = j; j = temp; } /* Output: a = 1 b = 2 After wrong swap: a = 1 b = 2 */ // End of Program 7.18.17.2. Pass Argument by References In order to change the value of an argument, we need to use the method called 'pass by references'. To do this, first, we need to locate the argument. This means that we should pass the address of the argument to the function. For example, when we call the function swap(), we should precede arguments 'a' and 'b' with the address operator '&': swap(&a, &b);

Satish

52

Satish kale C++ MANUAL Second, we need to tell the function that it is the contents, not the address, of the parameters that should be processed. This means that, in the definition of the function, we need to put the dereferencing operator '*' in front of the parameters: void swap(int *i, int *j){ int temp; temp = *i; *i = *j; *j = temp; } Accordingly, the prototype of the function should be changed to: void swap(int *i, int *j); The following is the revised program and its out put. / ******************************************** **************** Filename: swap2.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program illustrates that 'call by reference' will change the value of the original arguments ******************************************** ****************/ #include <iostream> using namespace std; void swap(int *i, int *j); main(){ int a = 1, b = 2;

Satish

53

Satish kale C++ MANUAL cout << " a = " << a << "\tb = " << b << endl; swap(&a, &b); cout << "After swap:\n"; cout << " a = " << a << "\tb = " << b << endl; return 0; } void swap(int *i, int *j){ int temp; temp = *i; *i = *j; *j = temp; } /* Output: a = 1 b = 2 After swap: a = 2 b = 1 */ // End of Program This time, the program gives the desired output. 7.18.17.3 Reference Arguments C++ has a feature called 'reference arguments'. The use of reference arguments will automatically involve the 'pass by reference' mechanism. When you call the function, you don't need to use '&' to explicitly pass the address; When you write the body of the function, you don't need the '*' sign neither. The only thing you need to do is to precede the argument with a '&' sign in the header of the function definition. Of course the prototype should be changed accordingly. The following is the 'reference arguments' version of the two preceding programs.

Satish

54

Satish kale C++ MANUAL / ******************************************** **************** Filename: swap2.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program illustrates that 'call by reference' will change the value of the original arguments ******************************************** ****************/ #include <iostream> using namespace std; void swap(int &i, int &j); main(){ int a = 1, b = 2; cout << " a = " << a << "\tb = " << b << endl; swap(a, b); cout << "After swap:\n"; cout << " a = " << a << "\tb = " << b << endl; return 0; } void swap(int &i, int &j){ int temp; temp = i; i = j; j = temp; }

Satish

55

Satish kale C++ MANUAL 7.18.18. VIRTUAL FUNCTIONS 7.18.18.1. Polymorphic Classes and Virtual Functions A polymorphic class is a class that includes a virtual function. A virtual function is a special member function that is declared as virtual in a base class and re-defined (called overridden) in derived classes. In the following example, 'person' is a polymorphic class, which includes a virtual function greeting(). The class 'chinese' inherits 'person' and overrides the virtual function greeting(). Example class person { public: virtual void greeting() { cout << "Hello!\n";} }; class chinese : public person { // greeting() is re-defined public: void greeting() { cout << "Ni Hao! I am a Chinese\n";} }; 7.18.18.2. Virtual Function Invocation Virtual functions are used to accomplish run-time polymorphism, which means using same interface for different methods. To do this, you need to invoke virtual functions through a pointer to a particular class type. The program below is an illustration. / ******************************************** ****************

Satish

56

Satish kale C++ MANUAL Filename: virtual.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program illustrates how to use virtual functions. ******************************************** ****************/ #include <iostream> using namespace std; class person { public: virtual void greeting() { cout << "Hello!\n";} }; class woman : public person { // greeting() is not overridden } class man : public person { // greeting() is overridden public: void greeting() { cout << "Hello! Lady first.\n";} }; main(){ person *p, b; woman d1; man d2; p = &b;

Satish

57

Satish kale C++ MANUAL p->greeting(); p = &d1; p->greeting(); p = &d2; p->greeting(); return 0;

} /* Output: Hello! Hello! Hello! Lady first. */ 7.18.18.3. Pure Virtual Functions and Abstract Classes A pure virtual function is a virtual function that has no definition in the base class. The format to declare a pure virtual function is: virtual type function_name(parameter-list) = 0; When a virtual function is made pure, all derived classes must provide their own definition, otherwise a compile-time error will occur. An abstract class is a class that contains pure virtual function(s). It is used as a foundation for derived classes but cannot be used directly to create objects. However, pointers to an abstract class are legal. This allows run-time polymorphism. / ******************************************** **************** Filename: abstract.cpp Author: Zhiwei Wang Date: July, 1997

Satish

58

Satish kale C++ MANUAL Description: A simple example of using abstract class An abstract class is a class that contains pure virtual function(s). A pure virtual function is a virtual function that has no definition in the base class. An abstract class cannot be used directly to create objects. However, pointers to an abstract class are allowed. ******************************************** ****************/ #include <iostream> using namespace std; class person { // 'person' is an abstract class public: virtual void greeting() = 0; // 'greeting()' is now a pure //virtual function }; class woman : public person { // greeting() must be overridden public: void greeting() { cout << "Hello!\n";} }; class man : public person { public:

Satish

59

Satish kale C++ MANUAL void greeting() { cout << "Hello! Lady first.\n";} }; main(){ // Abstract class cannot be used to create object 'b'. // so comments out the following line // person *p, b; // However, abstract class can be used to create a pointer // to it. person *p; woman d1; man d2; p = &d1; p->greeting(); p = &d2; p->greeting(); return 0;

} /* Output: Hello! Hello! Lady first. */ // End of Program 7.18.19. TEMPLATES 7.18.19.1. Generic Functions A generic function (also called template function) is a function that defines a general algorithm applicable to various types of data. A generic function is defined with the keyword template:

Satish

60

Satish kale C++ MANUAL template <class Ttype> ret-type func-name (parameter list) { // body of function } Ttype is a placeholder for the data type used by the function. In the following example, the function 'swap()' is a generic function that can be used to swap two numbers, characters, etc. / ******************************************** **************** Filename: swap.cpp Description: A simple example of using template ******************************************** ****************/ #include <iostream> using namespace std; // a function template template <class Whatever> void swap(Whatever &a, Whatever &b) { Whatever temp; temp = a; a = b; b = temp; } main(){ cout << "swap() can be used to swap two integers:\n"; int i=1, j=2; cout << "Original:\ti=" << i << ";\tj=" << j << ".\n"; swap(i, j);

Satish

61

Satish kale C++ MANUAL cout << "Swapped:\ti=" << i << ";\tj=" << j << ".\n"; cout << "swap() can be used to swap two real numbers:\n"; float num1=1.2, num2=3.4; cout << "Original:\tnum1=" << num1 << ";\tnum2=" << num2 << ".\n"; swap(num1, num2); cout << "Swapped:\tnum1=" << num1 << ";\tnum2=" << num2 << ".\n"; cout << "swap() can be used to swap two characters:\n"; char ch1='a', ch2='b'; cout << "Original:\tch1=" << ch1 << ";\tch2=" << ch2 << ".\n"; swap(ch1, ch2); cout << "Swapped:\tch1=" << ch1 << ";\tch2=" << ch2 << ".\n"; return 0; } /* Output: swap() can be used to swap two integers: Original: i=1; j=2. Swapped: i=2; j=1. swap() can be used to swap two real numbers: Original: num1=1.2; num2=3.4. Swapped: num1=3.4; num2=1.2. swap() can be used to swap two characters: Original: ch1=a; ch2=b. Swapped: ch1=b; ch2=a. */ // End of program 7.18.19.2. Generic Classes

Satish

62

Satish kale C++ MANUAL The general form to declare a generic class is: template <class Ttype> class class-name{ ... } Once a generic class is declared, you create an object of that class using the following format: class-name <type> variable-name; Example: / ******************************************** **************** Filename: queue.cpp Author: Zhiwei Wang Date: July, 1997 Description: This program gives an example of using generic classes and generic functions. The program implements a queue on an array. The class 'queue' is a generic class. You can use if for a queue of integers, 'float's, characters, etc. The member function 'enqueue()' adds an item to the queue, the function 'dequeue()' takes an item from the queue, and the function 'showqueue()' display the queue. 'menu' is a generic function. It can be used for a

Satish

63

Satish kale C++ MANUAL queue of integer items, 'float' items, 'char' items, etc. ******************************************** ****************/ #include <iostream> using namespace std; const int SIZE = 100; template <class QType> class queue { QType q[SIZE]; int head, tail, count; public: queue(); QType item; void enqueue(QType i); QType dequeue(); void showqueue(); }; template <class QType> queue<QType>::queue() { head = 0; tail = 0; count = 0; cout << "Queue created.\n"; } template <class QType> void queue<QType>::enqueue(QType i) { if (count == SIZE) { cout << "Queue is full.\n"; return; }

Satish

64

Satish kale C++ MANUAL q[tail++] = i; count++; tail %= SIZE; } template <class QType> QType queue<QType>::dequeue() { if (count == 0) { cout << "Queue is empty.\n"; return 0; } int temp; temp = head; head = (head+1)%SIZE; count--; return q[temp]; } template <class QType> void queue<QType>::showqueue() { if (count == 0) { cout << "Queue is empty.\n"; return; } int temp = head; for (int i=0; i<count; i++) { cout << q[temp] << ";"; temp = (temp+1)%SIZE; } } template <class QT> void menu(QT q) { int choice = 0; while (choice != 4) {

Satish

65

Satish kale C++ MANUAL cout << "What do you want to do? Type number 1, 2, 3, or 4.\n"; cout << "1. add an item to the queue.\n"; cout << "2. take an item from the queue.\n"; cout << "3. display the queue.\n"; cout << "4. quit.\n"; cin >> choice; if (choice == 4) return; switch (choice) { case 1: cout << "Enter an item, please: "; cin >> q.item; q.enqueue(q.item); cout << "\nItem enterred.\n"; break; case 2: cout << "The item to be served is: " << q.dequeue() << endl; cout << "\nDone.\n"; break; case 3: cout << "The queue is:\n"; q.showqueue(); break; default: cout << "Please type 1, 2, 3, or 4\n"; } } } main() { int i=0; while (i != 4) {

Satish

66

Satish kale C++ MANUAL cout << "You can build a queue of data type int, float, or char\n"; cout << "1. integer\t2. float\t3. char \t4. quit\n"; cout << "Enter your choice: (Type 1, 2, 3, or 4)\n"; cin >> i; if (i == 4) return 0; switch (i) { case 1: queue<int> iq; menu(iq); break; case 2: queue<float> fq; menu(fq); break; case 3: queue<char> cq; menu(cq); break; default: cout << "You have to choose 1, 2, 3, or 4.\n"; } } return 0; } // End of Program 7.18.19.3. Examples with More than One Generic Data Types You can use a comma-separated list for more than one generic data types, as shown in the example below:

Satish

67

Satish kale C++ MANUAL / ******************************************** **************** Filename: moretype.cpp Author: Zhiwei Wang Date: July, 1997 Description: An example of multiple generic data types ******************************************** ****************/ #include <iostream> using namespace std; template <class Type1, class Type2, class Type3> class record { Type1 name; Type2 value; Type3 info; public: record(Type1 a, Type2 b, Type3 c) {name=a; value=b; info=c;} void display(); }; template <class Type1, class Type2, class Type3> void record<Type1, Type2, Type3>::display() { cout << "Item1:\t" << name << endl; cout << "Item2:\t" << value << endl; cout << "Item3:\t" << info << endl; } main() {

Satish

68

Satish kale C++ MANUAL record<char*, int, double> person("John", 32, 3245.34); person.display(); cout << endl; record<int, char, char*> note(3, 'A', "Call me"); note.display(); return 0; } /* Output: Item1: John Item2: 32 Item3: 3245.34 Item1: 3 Item2: A Item3: Call me */ // End of Program 7.18.20. Exceptions Error codes returned from procedures do not convey much information to the calling procedure. It is usually a number that indicates the cause of failure. But in many situations, it would be very helpful if more informaiton about the cause of failure is available to the caller. A simple error code cannot fulfill this goal. A popular alternative to returning error code is to raise exceptions. Exceptions are run-time anomalies that a program may detect. They indicate an abnormal conditon that should not be encountered.

Satish

69

Satish kale C++ MANUAL 7.18.20.1. The throw Statement In C++, an exception is raised using a throw expression, which is composed of the keyword throw followed by an expression. Example: NodeData Queue::Dequeue() { NodeData Temp; // Since "End of File" is an expected condition for a Queue, we // must do something to signal EOF. So, we use the Catch/Throw // mechanism in C++, and modify the exception name to reflect that // this is a Queue. if (IsEmpty()) throw EOQ(); ToHead(); Temp = Read(); Delete(); } return Temp;

In the previous example, EOQ is a class defined inside class Queue by the following statement: class EOQ {}; The expression followed the throw keyword is an invocation of the constructor of EOQ. This invocation creates an object of EOQ, which is thrown by the throw statement. 7.18.20.2. The try Statement

Satish

70

Satish kale C++ MANUAL The code that can throw exceptions should be enclosed in a try block. Following the try block is a list of catch clauses. Example try { Current = SearchQ.Dequeue(); // If we get here, we successfully dequeued a state from // the Search Queue, so we must decrement the size of the // Leaf List. LeafList--; } catch (PriorityQueue::EOQ) { NodesRemaining = FALSE; cout << "\nThere is no solution to this Puzzle!" << endl; break; } The general forms of try and catch statement are shown as follows: try { // try block } catch (type1 arg) { // catch block } catch (type2 arg) { //catch block } . . . catch (typen arg) {

Satish

71

Satish kale C++ MANUAL // catch block } When an exception is thrown, if its data type matchs the data type specified by a catch statement, the exception will be caught, and the corresponding catch statement will be executed. All the other catch statements will be bypassed. When an exception is caught, arg will receive it value. Example: #include <iostream> using namespace std; main() { try { cout << "begin" << endl; throw 100; cout << "this will not be shown" << endl; } catch (int i) { cout << "Caught an exceptionm, the value is: "; cout << i << endl; } cout << "The End" << endl; } output: begin Caught an exceptionm, the value is: 100 The End If you change the data type in the catch statement from int to a different type,

Satish

72

Satish kale C++ MANUAL then the exception will not be caught and abnormal termination of the program will occur. Example: #include <iostream> using namespace std; void Ehandler(int i) { try { if (i==0) throw "Value is zero.."; else throw i; } catch (int e) { cout << "Caught: " << e << endl; } catch (char *str) { cout << "Caught: " << str << endl; } } main() { cout << "Begin" << endl; Ehandler(1); Ehandler(0); Ehandler(2); } return 0;

output: Begin Caught: 1 Caught: Value is zero..

Satish

73

Satish kale C++ MANUAL Caught: 2 7.18.20.3. Caught all Exceptions Example: Using Multiple catch Statements #include <iostream> using namespace std; void Ehandler(int i) { try { switch (i) { case 0: throw "Value is zero."; break; case 1: throw 'a'; break; case 2: throw 3.14; break; default: throw i; } } catch (int e) { cout << "Caught: " << e << endl; } catch (char * e) { cout << "Caught: " << e << endl; } catch (...) { cout << "Caught one." << endl; } }

Satish

74

Satish kale C++ MANUAL main() { cout << "Begin" << endl; Ehandler(0); Ehandler(1); Ehandler(2); Ehandler(3); return 0; } Output: Begin Caught: Value is zero. Caught one. Caught one. Caught: 3 7.18.20.4. Restricting Exceptions If necessary, you can restrict the types of exceptions a function can throw. The general form of doing this is: ret-type func-name(arg-list throw (type list) { // function body } Example #include <iostream> using namespace std; void Ehandler(int i) throw (int, char, float, char *) { switch (i) { case 0: throw "Value is zero.";

Satish

75

Satish kale C++ MANUAL break; case 1: throw 'a'; break; case 2: throw 3.14; break; default: throw i; }

main() { cout << "Begin\n"; try { Ehandler(0); } catch (int i) { cout << "Caught an integer\n"; } catch (char c) { cout << "Caught a character\n"; } catch (float n) { cout << "Caught a float\n"; } catch (char * str) { cout << "Caught a string\n"; } cout << "end" << endl; } Throwing any other types of exceptions will cause abnormal termination. If you don't want to throw any exceptions, use an empty list. Example #include <iostream> using namespace std;

Satish

76

Satish kale C++ MANUAL // This function can throw no exception void Ehandler(int i) throw () { switch (i) { case 0: throw "Value is zero."; break; case 1: throw 'a'; break; case 2: throw 3.14; break; default: throw i; } }

Satish

77

Das könnte Ihnen auch gefallen