A Complete Guide to Programming in C++ part 72 docx

10 242 0
A Complete Guide to Programming in C++ part 72 docx

Đang tải... (xem toàn văn)

Thông tin tài liệu

POINTERS TO FUNCTIONS ■ 689 ᮀ Using Pointers to Functions In C++ the name of a function is a constant pointer to that function. It addresses the machine code for the function. This is a situation that we have already seen for arrays— the array name is also a constant pointer to the first array element. There are many uses for pointers to functions. You can save them in an array to form a jump table. Individual functions are then accessible via an index. A pointer to a function can also be passed as an argument to another function. This makes sense if the function you are calling needs to work with different functions depending on the current situation. The standard function qsort() is an example of this. qsort() uses the quick sort algorithm to sort an array. Depending on the type of the array elements and the sort crite- ria, the qsort() function will expect as argument another comparison function. ᮀ Declaring Pointers to Functions A pointer to a function is declared as follows: Syntax: type (* funcptr)( parameter_list ); This defines the variable funcptr, which can store the address of a function. The func- tion has the type type and the parameter list stated. The first pair of parentheses is also important for the declaration. The statement type *funcptr(parameter_list); would declare a function funcptr that returned a pointer. Now let’s point funcptr to the function compare() and call compare() via the pointer. Example: bool compare(double, double); // Prototype bool (*funcptr)(double, double); funcptr = compare; (*funcptr)(9.1, 7.2); Calling (*funcptr)() is now equivalent to calling compare(). The declaration of compare() is necessary to let the compiler know that compare is the name of a func- tion. In the program shown opposite, functab is an array with four pointers to functions of the void type, each of which expects a C string as an argument. functab is initial- ized by the functions stated in its definition and thus functab[0] points to error_message(), functab[1] to message(), etc. When the program is exe- cuted, the function with the specified index is called. 690 ■ CHAPTER 30 MORE ABOUT POINTERS ■ COMPLEX DECLARATIONS 1 st Example: 3. 0. strptr is a 1. pointer to 2. an array with 50 elements of type 3. char. 1. 0. 2. char (* strptr) [50] 2 nd Example: 5. 6. 5. 3. 1. 0. 2. 4. 0. func is a 1. function with return value of type 2. pointer to 3. an array with elements of type 4. pointer to 5. long. 0. funcptr is a 1. pointer to 2. a function with return value of type 3. pointer to 4. an array with elements of type 5. pointer to 6. char. 4. 2. 0. 1. long * (* func () ) [] 3 rd Example: char * (* (* funcptr ) () ) [] 3. COMPLEX DECLARATIONS ■ 691 Operator Significance Array with elements of type Function with return value of type Pointer to Reference to [] () * & ᮀ Operators and Complex Declarations In the declaration and definition of a function or a variable the same operators that you find in expressions are used in addition to the base type and the name. These operators are: A complex declaration always uses more than one of these operators. Example: char *strptr[50]; This declares strptr as an array of pointers to char. In a declaration, a combination of the three operators is permissible, however, the following exceptions apply: ■ the elements of an array cannot be functions ■ a function cannot return a function or an array (but it can return a pointer to a function or an array). Operators have the same precedence in declarations as in expressions. You can use parentheses to redefine the order of precedence. ᮀ Rules When a complex declaration is evaluated, the following rules are applied: 0. Always start with the identifier being declared. Then repeat the following steps until all the operators have been resolved: 1. If the parentheses/brackets () or [] are on the right, they are interpreted. 2. If there is nothing or just a right bracket on the right ), the asterisk on the left is interpreted, if it exists. At last the base type is interpreted. This proceeding is demonstrated by the example opposite. The above rules apply to both the function and each of its arguments. 692 ■ CHAPTER 30 MORE ABOUT POINTERS 1st Example: typedef DayTime FREETIME; FREETIME timeArr[100]; 2nd Example: typedef struct { double re, im; } COMPLEX; COMPLEX z1, z2, *zp; 3rd Example: typedef enum { Mo, Tu, We, Th, Fr } WORKDAY; WORKDAY day; 4th Example: typedef enum { Diamonds, Hearts, Spades, Clubs } COLOR; typedef enum { seven, eight, nine, ten , jack, queen, king, ace } VALUE; typedef struct { COLOR f; VALUE w; } CARD; typedef CARD[10] HAND; HAND player1, player2, player3; ■ DEFINING TYPENAMES DEFINING TYPENAMES ■ 693 ᮀ The typedef Keyword C++ allows you to give types a new name using the keyword typedef. Example: typedef unsigned char BYTE; This defines the type name BYTE, which can then be used as an abbreviation of the unsigned char type. The statement Example: BYTE array[100]; will then define an array array with 100 elements of the unsigned char type. Type names are normally uppercase, although this is not mandatory. Examples: typedef int* INTPTR; typedef enum{ RED, AMBER, GREEN } Lights; Here, INTPTR identifies the type “pointer to int” and Lights is an enumerated type. The new type name always assumes the position of a variable name in a typedef definition. Omitting the typedef prefix will define a variable name but not a new type name. Type definitions do not allocate memory and do not create a new type. They simply introduce a new name for an existing type. Example: typedef char* (*PTR_TO_FUNC)(); The type name PTR_TO_FUNC is an abbreviation for the type “pointer to a function that returns a pointer to char.” The declaration Example: PTR_TO_FUNC search; is then equivalent to char* (*search)(); ᮀ Advantages The major advantage of using typedef is that it improves the readability of your pro- grams, especially when complex types are named. One additional advantage is that you can isolate platform dependent types. When a program is ported to another platform, you only need to change the platform dependent type once in the typedef definition. 694 ■ CHAPTER 30 MORE ABOUT POINTERS // matrix.h: Representing dynamic matrices. // #include <stdexcept> #include <iostream> using namespace std; class Row { double *ro; int size; public: Row( int s) { size = s; ro = new double[s]; } ~Row(){ delete[]ro; } double& operator[](int i) throw(out_of_range) {if(i < 0 || i > size) throw out_of_range("Column index: Out of Range\n"); else return ro[i]; } }; class Matrix { Row **mat; // Pointer to array of rows int lines, cols; // Number of rows and columns public: Matrix(int ro , int co ) { lines = ro; cols = co; mat = new Row*[lines]; for(int i=0; i < lines; i++) mat[i] = new Row(cols); } ~Matrix() { for(int i=0; i < lines; i++) delete mat[i]; delete[] mat; } int getLines() const { return lines; } int getCols() const { return cols; } Row& operator[](int i) throw(out_of_range) { if(i < 0 || i > cols) throw out_of_range("Row index: Out of Range\n"); else return *mat[i]; } }; ■ APPLICATION: DYNAMIC MATRICES Class Matrix APPLICATION: DYNAMIC MATRICES ■ 695 Now let’s develop an application that uses a class to represent dynamic matrices. Matri- ces are used for computing vectors needed to move, rotate, or zoom images in graphics programming, for example. ᮀ The Matrix Class Memory is to be allocated dynamically to a matrix m at runtime. Additionally, it should be possible to use the index operator to access the elements of the matrix. Example: m[i][j] // Element in row i, column j The class will therefore need a dynamic member to reference the matrix. As you already know, a matrix is a single-dimensional array whose elements are single-dimensional arrays themselves. The class Row, which can be used to represent single-dimensional arrays of double values, is defined opposite. The index operator is overloaded for the Row class to allow an exception of the out_of_range type to be thrown for invalid indices. The Matrix class contains a dynamic member, mat, which can address an array of pointers to Row objects. mat is thus a pointer to a pointer. ᮀ Constructor, Destructor, and Subscript Operator The constructor in the Matrix class creates an array of lines pointers to objects of the Row type. A loop is then used to allocate memory to the rows dynamically. In contrast, the destructor releases the memory occupied by the line arrays first, before releasing the space occupied by the pointer array mat. The subscript operator in the Matrix class returns the line array i for a given index i. When the following expression is evaluated Example: m[2][3] the first call is to the subscript operator of the Matrix class, which returns a line array to index 2. Then the subscript operator of the Row class is called for the line array. It returns a reference to the double value at index 3. You will be enhancing the Matrix class in the exercises to this chapter by overload- ing the copy constructor and the assignment, for example. exercises 696 ■ CHAPTER 30 MORE ABOUT POINTERS #include <iostream> using namespace std; char* color[] = {"WHITE", "PINK", "BLUE", "GREEN" }; int main() { cout << *color[1] << " " << *color << " " << *(color[3] + 3) << " " << color[2] + 1 << " " << *( *(color + 1) + 3) << endl; return 0; } Since the comparison function compare will be called as a C function, it should be declared and defined as extern "C" int compare( ); Refer to the Appendix “Binding C Functions.” ✓ NOTE ■ EXERCISES Listing for exercise 1 For exercise 3 The standard function qsort() #include <cstdlib> void qsort( void* array, size_t n, size_t size, int (*compare)(const void*, const void*)); The function qsort(), ”quick sort,” sorts an array of n elements whose first element is pointed to by array. The size of each element is specified by size. The comparison function pointed to by compare is used to sort the content of the array in ascending order . qsort() calls the function with two arguments that point to the elements being compared. You will normally need to define the comparison function yourself.The function must return an integer less than, equal to, or greater than zero if the first argument is less than, equal to, or greater than the second. EXERCISES ■ 697 You can use the SelectionSort() function defined in Exercise 4 of Chapter 17 as an algorithm for sorting the int values in this exercise. Use the standard function qsort(), whose prototype is defined opposite, as quick sort algorithm for this exercise. ✓ NOTE Exercise 1 What does the program opposite output on screen? Exercise 2 Write a function min() that computes and returns the minimum of two positive numbers.The function expects a variable number of unsigned int values as arguments.The last argument must be the number 0. Exercise 3 Write a C++ program that compares the speed of the quick sort and selection sort algorithms Sort two identical sequences of random numbers of the type int to test the sort algorithms. Read the maximum number of random numbers from the keyboard and allocate the needed memory dynamically. Display the time in seconds required for the sort operation on screen after each sort operation. Exercise 4 Write additional methods to complete the Matrix class. ■ Add a const version of the subscript operator to the Row and Matrix classes. Use an inline implementation. ■ Define a constructor for the Matrix class.The constructor dynamically allocates a matrix with a given number of rows and columns, and initial- izes the matrix elements with a given value.Also write a copy construc- tor. ■ Overload the assignment operator = and the compound assignment oper- ator +=. Addition is defined for two n ϫ n matrices, A and B, which have equal num- bers of rows and columns.The sum C is a n ϫ n matrix whose elements are computed by adding elements as follows C[i,j] = A[i,j] + B[i,j] for i, j = 0, , n-1 ■ Test the Matrix with a suitable main function that calls all the methods. Display the results of the calculations on screen. solutions 698 ■ CHAPTER 30 MORE ABOUT POINTERS ■ SOLUTIONS Exercise 1 Screen output: P WHITE E LUE K Exercise 2 // // minivar.cpp // Defines and tests the function min(), which // computes and returns the minimum of positive integers. // The function expects a variable number of arguments // with unsigned int types. // The last argument must be 0! // #include <stdarg.h> unsigned int min( unsigned int first, ) { unsigned int minarg, arg; va_list argptr; // Pointer to optional arguments if( first == 0) return 0; va_start( argptr, first); minarg = first; while( (arg = va_arg(argptr, unsigned int) ) != 0) if( arg < minarg) minarg = arg; va_end (argptr); return minarg; } // A small function main() for testing #include <iostream> using namespace std; int main() { cout << "\nThe minimum of : 34 47 19 22 58 " << "is: " << min(34, 47, 19, 22, 58, 0) << endl; return 0; } . situation that we have already seen for arrays— the array name is also a constant pointer to the first array element. There are many uses for pointers to functions. You can save them in an array to form. return value of type Pointer to Reference to [] () * & ᮀ Operators and Complex Declarations In the declaration and definition of a function or a variable the same operators that you find in expressions. functions ■ a function cannot return a function or an array (but it can return a pointer to a function or an array). Operators have the same precedence in declarations as in expressions. You can use parentheses

Ngày đăng: 06/07/2014, 17:21

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan