Cpp Chapter 8: Adventures in Functions Part3

8.2.6 Objects, Inheritance, and References

) You might use ostream object cout and ofstream object fout(your declaration), and the object fout could share the methods of ostream class. The language features of passing class features from one to another is called class inheritance. In this example, ostream is termed base class and ofstream is termed derived class. Methods like precision() and setf() in ostream class is also available to ofstream class objects, so you could use same methods will handing console output and file output.

) A base class reference could refer to a derived class object without type cast.

The following example illustrates these features:

 1 // filefunc.cpp -- function with ostream & parameter
 2 #include <iostream>
 3 #include <fstream>
 4 #include <cstdlib>
 5 using namespace std;
 6 
 7 void file_it(ostream & os, double fo, const double fe[], int n);
 8 const int LIMIT = 5;
 9 int main()
10 {
11     ofstream fout;
12     const char * fn = "ep-data.txt";
13     fout.open(fn);
14     if (!fout.is_open())
15     {
16         cout << "Can't open " << fn << ". Bye.\n";
17         exit(EXIT_FAILURE);
18     }
19     double objective;
20     cout << "Enter the focal length of your telescope objective in mm: ";
21     cin >> objective;
22     double eps[LIMIT];
23     cout << "Enter the focal lengths, in mm, of " << LIMIT << " eyepieces:\n";
24     for (int i = 0; i < LIMIT; i++)
25     {
26         cout << "Eyepiece #" << i+1 << ": ";
27         cin >> eps[i];
28     }
29     file_it(fout, objective, eps, LIMIT);
30     file_it(cout, objective, eps, LIMIT);
31     cout << "Done\n";
32     return 0;
33 }
34 
35 void file_it(ostream & os, double fo, const double fe[], int n)
36 {
37     ios_base::fmtflags initial;
38     initial = os.setf(ios_base::fixed); // save initial formatting state
39     os.precision(0);
40     os << "Focal length of objective: " << fo << " mm\n";
41     os.setf(ios::showpoint);
42     os.precision(1);
43     os.width(12);
44     os << "f.l. eyepiece";
45     os.width(15);
46     os << "magnification" << endl;
47     for (int i = 0; i < n; i++)
48     {
49         os.width(12);
50         os << fe[i];
51         os.width(15);
52         os << int(fo / fe[i] + 0.5) << endl;
53     }
54     os.setf(initial);
55 }

29-30) file_it() recieves an ostream-class reference as first parameter, here passes fout and cout consecutively, proving that base-class reference could also accpet derive-class objects without type cast, so these two lines print stuff on console and print it in a file, both using ostream class formatting features.

39/42) precision() specifies the number of digits displayed right to the decimal

43/45/49/51) width() specifies output width range for next output(width(0) means no mandatory stretch or trimming: just display it according to its original quantity)

37/38/54) Code like this is observed:

1 ios_base::fmtflags initial;
2 initial = os.setf(ios_base::fixed);
3 ...
4 os.setf(initial);

The first row declares a variable initial as type ios_base::fmtflags for storing initial pattern. Then initial was assigned to the return value of os.setf(), which returns the original format settings of the ostream object before "setf". After the process, it uses os.setf(initial) to retain the initial formatting by using the stored initial pattern.

8.2.7 When to Use Reference Arguments

There are two main reasons for using reference arguments:

1) To allow you to alter a data object in the calling function

2) To speed up the program by passing a reference instead of an entire data object

Guidelines of choosing between reference, pointer and passing by value:

  No data modifying modify data
build-in data type pass by value pointer
array const pointer pointer
structure const pointer/reference pointer/reference
class object const reference reference

8.3 Default Arguments

) A default argument is a value that's used automatically if you omit the corresponding actual argument from a function call.

) Use function prototype for default arguments.

char * left(const char * str, int n = 1);

In this way you make n a default argument, if you omit value of n, the program will take n for 1.

left(arr, 1);
left(arr);// functions in the same way

) When using a function with an argument list, you must add defaults from left to right:

int f1(int n, int m = 4, int l = 5); // valid
int f2(int n, int m = 3, int l); // invalid
int f3(int n = 1, int m = 2, int l = 3); // valid

For instance, the f1() allows calls with one/two/three parameters. You can't skip arguments like this:

f1(2, , 3); // invalid, doesn't set m to 4

The following exapmle illustrates the features:

 1 // left.cpp -- string function with a default argument
 2 #include <iostream>
 3 const int ArSize = 80;
 4 char * left(const char * str, int n = 1);
 5 int main()
 6 {
 7     using namespace std;
 8     char sample[ArSize];
 9     cout << "Enter a string:\n";
10     cin.get(sample, ArSize);
11     char *ps = left(sample, 4);
12     cout << ps << endl;
13     delete [] ps;
14     ps = left(sample);
15     cout << ps << endl;
16     delete [] ps;
17     return 0;
18 }
19 
20 char * left(const char * str, int n)
21 {
22     if (n < 0)
23         n = 0;
24     char * p = new char[n+1];
25     int i;
26     for (int i = 0; i < n && str[i]; i++)
27         p[i] = str[i];
28     while (i <= n)
29         p[i++] = '\0';
30     return p;
31 }

猜你喜欢

转载自www.cnblogs.com/fsbblogs/p/9703923.html