Previous | Contents | Index |
#include <complex.h>
class c_exception { friend complex exp(const complex &); friend complex sinh(const complex &); friend complex cosh(const complex &); friend complex log(const complex &); friend int complex_error(c_exception &); public: int type; char *name; complex arg1; complex arg2; complex retval; public: c_exception(char *, const complex &, const complex & = complex_zero); };
Objects of this class handle exceptions for complex arithmetic. This includes information on functions, parameters, error types, and default return values.
complex arg1
Is the left argument of the function that incurred the error.complex arg2
Is the right argument of the function that incurred the error.char *name
Is the name of the function that incurred the error.complex retval
Is the value to be returned by the function that incurred the error. You may use the complex_error(c_exception &) function to change this value.int type
Is one of these kinds of error: SING, OVERFLOW, or UNDERFLOW.
c_exception(char *function_name, const complex &function_arg1, const complex &function_arg2 = complex_zero)
Constructs a complex arithmetical exception object, with reference to the name and arguments of the function that incurred the error.
int complex_error (c_exception &error_information)
Is the default error-handling function that is called by certain complex arithmetical functions in this package (namely, cosh, exp, log, and sinh) when those functions detect an arithmetical error. You may replace this function with your own function that takes an identical parameter list and returns a value as specified in the following table:
Return Value from Error-handling Function Action Taken by Complex Arithmetical Function 0 Set the global value errno ; if the error type is SING , print an error message. non 0 Do not set errno ; do not print an error message. To substitute your own error-handling function, pass a pointer to your function to the set_complex_error function. (See the Function section under Global Declarations for the complex package.)
The complex arithmetical functions that invoke the error handling function always return the value specified in error_information.retval. Your error-handling function may set this value.
The generic package provides ways to simulate parameterized types by allowing the instantiation of class declarations using the macro facilities of the C++ preprocessor. You can use the generic package to construct container classes. The actual types of the data members are passed at compile time as parameters to the class when you use the class name.
To declare a generic type:
#define YOUR_CLASS_NAME(TYPE_PARAMETER_NAME) name2(TYPE_PARAMETER_NAME, YOUR_CLASS_NAME) |
#define YOUR_CLASS_NAMEdeclare(TYPE_PARAMETER_NAME) class {...}; #define YOUR_CLASS_NAMEimplement(TYPE_PARAMETER_NAME) ... |
declare(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) |
implement(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) |
YOUR_CLASS_NAME(ACTUAL_TYPE_NAME) object1, object2; |
These declarations are used by the generic package but they are not members of any class.
#include <generic.hxx>Alternative Header
#include <generic.h>
TYPE, TYPE1, TYPE2---The types for which this class is parameterized; TYPE, TYPE1, or TYPE2 must be an identifier.
CLASS---The class that is parameterized. For a vector of integers, for example, CLASS is vector and TYPE is int.
typedef int (*GPT)(int, char *); int genericerror(int n, char *msg);
GPT
Is a pointer to a generic error-handling function.
int genericerror (int n, char *msg)
Is the default error-handling function; it prints an error number (n) and message (msg) on cerr and calls abort().
Macros provide preprocessor facilities for simulating parameterized types. The following macros are defined for the generic package:callerror(CLASS, TYPE, N, S)
Calls the current error handler for a given instance of a parameterized class. CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers); the type must be an identifier (for example, char* is not valid). N denotes the first argument to pass to the error handler; the default is the function genericerror(int, char*). S denotes the second argument to pass to the error handler.declare(CLASS, TYPE)
Declares the class specified by a macro with the name of the generic class. The word declare follows the class name (for example, vectordeclare). It also defines the inline member functions of the class. CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers). The type must be an identifier (for example, char* is not valid).declare2(CLASS, TYPE1,TYPE2)
Declares the class specified by a macro with the name of the generic class. The name is followed by the word declare2. The declare2 macro differs from the declare macro only in that you use it to declare two type parameters, TYPE1 and TYPE2.errorhandler(CLASS, TYPE)
Is the name of the pointer to the error handler for a given instance of a parameterized class (for example, intvectorhandler to handle errors for a vector of integers). CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers). The type must be an identifier (for example, char* is not valid).implement(CLASS, TYPE)
Defines the noninline member functions of a class, specified by a macro with the name of the generic class. The name is followed by the word implement (for example, vectorimplement). The implement macro takes the same arguments as the declare macro.implement2(CLASS, TYPE1,TYPE2)
Defines the noninline member functions of a class, specified by a macro with the name of the generic class. The name is followed by the word implement2. The implement2 macro differs from the implement macro only in that you use it to declare two type parameters, TYPE1 and TYPE2.name2(S1,S2)
Concatenates two identifier segments to form a new identifier using the ## operator.name3(S1,S2,S3)
Concatenates three identifier segments to form a new identifier using the ## operator.name4(S1,S2,S3,S4)
Concatenates four identifier segments to form a new identifier using the ## operator.set_handler(CLASS, TYPE, HANDLER)
Specifies a function as the current error handler for a given instance of a parameterized class. Initially, the error-handling function is set to genericerror(int, char*). CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers); the type must be an identifier (for example, char* is not valid). HANDLER denotes a pointer to the function you want to set to the new error handler. Also, you can use the set_handler macro in a function declaration or definition.
The following program shows the use of the genericerror function and associated macros:
extern "C" { #include <stdlib.h> #include <stddef.h> #include <stdio.h> } #include <generic.hxx> #define my_vector(T) name2(T, my_vector) // Declare a vector of objects of type T (the class and extern data) #define my_vectordeclare(T) \ class my_vector(T) \ { \ private: \ int s; \ T *p; \ public: \ my_vector(T)(int); \ ~my_vector(T)(); \ T &operator[](int); \ }; \ extern GPT errorhandler(my_vector, T); \ extern GPT set_handler(my_vector, T, GPT); // Implement a vector of objects of type T // (Define the functions and global data) #define my_vectorimplement(T) \ my_vector(T)::my_vector(T)(int size) \ { \ s = size; \ p = new T[size]; \ } \ my_vector(T)::~my_vector(T)() \ { \ delete[] p; \ } \ T &my_vector(T)::operator[](int i) \ { \ if(i < 0 || i >= s) \ { \ callerror(my_vector, T, i, "Index out of bounds"); \ static T error_object; \ return error_object; \ } \ return p[i]; \ } \ GPT errorhandler(my_vector, T) = &genericerror; \ GPT set_handler(my_vector, T, GPT new_genericerror) \ { \ GPT old_genericerror = errorhandler(my_vector, T); \ errorhandler(my_vector, T) = new_genericerror; \ return old_genericerror; \ } // Declare and implement vector of int declare(my_vector, int) implement(my_vector, int) // Error-handling function my_handler( int n, char *msg ) { fflush(stderr); printf("in my_handler(%d,\"%s\")\n", n, msg); fflush(stdout); return 0; } int main(int argc, char *argv[]) { my_vector(int) v1(10); GPT old_error_handler; // Set the handler to a function that does not abort old_error_handler = set_handler(my_vector, int, &my_handler); v1[12345] = 0; // Restore the handler and cause an error // This should abort old_error_handler = set_handler(my_vector, int, old_error_handler); v1[12345] = 0; return EXIT_SUCCESS; } |
vector Package
Classes in the iostream package provide methods to handle input and output streams, including reading and writing built-in data types. You also can extend certain methods described here to handle class types.
This package includes, among others, the classes ios and streambuf, and the subclasses derived from these base classes. Figure 4-1 shows the inheritance structure of the iostream package. In the diagram, arrows point from the base classes to derived classes.
The istream (input stream) class supports input operations (extractions); the ostream (output stream) class supports output operations (insertions). The iostream class derives from both istream and ostream, and supports both extractions and insertions.
The following stream objects are predefined:
cin | An istream_withassign object linked to standard input |
cout | An ostream_withassign object linked to standard output |
cerr | An ostream_withassign object linked to standard error that supports unbuffered output |
clog | An ostream_withassign object linked to standard error that supports buffered output |
To generate output, you apply the insertion operator (<<) to cout, as shown in the following example:
cout << "Hello\n" ; |
Figure 4-1 Inheritance Diagram for the iostream Package
Obtaining input is similar to generating output, except that you apply the extraction operator (>>) to cin, as shown in the following example:
int eye, jay ; cin >> eye >> jay ; |
If you include these fragments of code in a program, your system expects users to type in two integer values (for eye and jay) from a terminal. The iostream package supplies predefined extraction and insertion operators for all built-in data types, including char*.
This package also supports file manipulation. To connect a specific file to your program, instantiate one of the following class types:
To format within character arrays, the iostream package includes the following associated class types:
On systems with IEEE floating-point arithmetic, certain values may be printed as symbols for Infinity (for example, INF) or Not a Number (for example, NaN). |
Deriving Your Own Class from ios
If you derive your own class from the ios class, or from one of its derived classes, the ios subobject must be initialized properly during instantiation. Specifically, you must ensure that the streambuf pointer within the ios subobject is valid.
To do this, you can specify the ios(streambuf*) constructor as a member initializer for your class constructor. Optionally, you can call the ios::init(streambuf*) member function.
Thread Safety
The predefined stream objects, cerr , cin , clog , and cout are thread safe only for individual calls into the DEC C++ Class Library. You must provide synchronization around sequences of calls. For more information on synchronizing access to predefined stream objects, see the section on Global Declarations in this chapter.
User-defined stream objects are not thread safe, so you must provide synchronization around individual calls as well as sequences of calls. For more information on synchronizing access to user-defined objects, see Chapter 6 and the section on Global Declarations in this chapter.
The ios member function sync_with_stdio() is not thread safe. If your application calls this function, it must make the call before any threads use cerr , cin , clog , or cout .
These declarations are used by the iostream package but they are not members of any class.
#include <iostream.hxx>Alternative Header
#include <iostream.h>
typedef long streamoff typedef long streampos ios &dec(ios &s); ios &hex(ios &s); ios &oct(ios &s); ios &lock(ios &s); ios &unlock(ios &s); istream &ws(istream &i); ostream &endl(ostream &o); ostream &ends(ostream &o); ostream &flush(ostream &o);
typedef long streamoff
Is the type representing a character offset into a stream. For more information, see the description of the seekoff and seekpos functions in the streambuf class.typedef long streampos
Is the type representing a character position in a stream. For more information, see the description of the seekoff and seekpos functions in the streambuf class.
The following functions insert values into a stream, extract values from a stream, or specify the conversion base format. For more information on the conversion base format flags, see the ios class.ios &dec(ios &s)
Sets the conversion base format for s to decimal, essentially clearing the ios::oct and ios::hex flags and setting the ios::dec flag.ios &hex(ios &s)
Sets the conversion base format for s to hexadecimal, essentially clearing the ios::oct and ios::dec flags and setting the ios::hex flag.ios &oct(ios &s)
Sets the conversion base format for s to octal, essentially clearing the ios::dec and ios::hex flags and setting the ios::oct flag.istream &ws(istream &i)
Extracts (skips) white-space characters from i.ostream &endl(ostream &o)
Ends a line by inserting a new-line character into o and flushing o.ostream &ends(ostream &o)
Ends a string by inserting a null '/0' character into o.ostream &flush(ostream &o)
Flushes o.
The following unparameterized manipulators are for use in synchronizing access to the predefined stream objects, cerr, cin, clog, and cout:ios &lock(ios &s)
Locks s if s is one of the predefined stream objects.ios &unlock(ios &s)
Unlocks s if s is one of the predefined stream objects.If your application needs to lock two or more of these objects at the same time, your application must adhere to the following locking order:
- cin
- cerr
- clog
- cout
For example, if your application needs to lock both cerr and cout , lock cerr first and cout second. The unlocking order is not important.
Keep in mind that when your application calls a member function for a predefined stream object, the member function will typically lock the object for the duration of the call. Therefore, if your application has locked one of the stream objects and then uses another, this use must also adhere to the predefined locking order. For example, your application should not send output to cerr while cout is locked.
The locking order necessarily matches the default ties between the stream objects as follows:
- cin is tied to cout
- cerr is tied to cout
- clog is tied to cout
- cout has no ties
Any input/output operation on a stream object causes the iostream package to flush the object to which it is tied. Thus, an output to cerr flushes cout .
#1 |
---|
#include <iostream.hxx> #include <iomanip.hxx> int main () { int value = 10; cout << hex << value << ','; // Change the base conversion format to // hexadecimal; note that the default is // decimal as set by the ios constructors. cout << value << ','; // The base conversion format set in the // previous line is still active. cout << dec << value << endl; // Change the base conversion format to // decimal; lastly, insert a new-line // character into the stream and flush // cout. return 0; } |
Previous Next Contents Index