Effective C ++ 2e Item 24

zhaozj2021-02-11  172

Terms 24: Careful choices between function overload and setting parameters

The reason for confusing the function overload and setting parameters defaults is that they all allow a function to be called in a variety of ways:

Void f (); // f is overloaded Void F (int x);

f (); // Call f () f (10); // call f (int)

Void g (int x = 0); // G has a // default parameter value

g (); // Call G (0) g (10); // Call G (10)

So, when should I use?

The answer depends on the other two questions. First, there is a value that can be used as a default? Second, how many algorithms do you want to use? In general, if a suitable default value can be selected and only one algorithm is used, the default parameter is used (see Terms 38). Otherwise, use the function overload.

Below is a function of up to the maximum maximum value of five int. This function is used - deep breath, see clearly --std :: numeric_limits :: min () as the default parameter value. Waiting for another introduction to this value, here is the code for the function:

Int Max (int A, int b = std :: min (), int c = std :: numeric_limits :: min (), int D = std :: numeric_limits :: Min (), int E = std :: numeric_limits :: min ()) {int Temp = a> b? A: b; Temp = Temp> C? Temp: C; Temp = Temp> D? Temp: D; RETURN TEMP> E? TEMP: E;

It can now be relaxed. std :: numeric_limits :: min () is a C standard library with a unique new method that is defined in C, which is the int_min Hongfa defined in . The thing indicated - handles the minimum possible value of the intimate generated by your C original code compiler. Yes, its syntactic departures from the conciseness of C, but behind those colons and other strange syntax, it is reasonable.

Suppose wants to write a function template, its parameter is a fixed digital type, and the function generated by the template can print the minimum value represented by "Instantiated Type". This template can be written like this:

Template void printminimumValue () {cout << is expressed as the minimum of T type;}

If you just write this function with and , you will feel very difficult because I don't know what T is, so I don't know if the print int_min is DBL_MIN, or any other type of value.

In order to avoid these difficulties, standard C libraries (see clause 49) define a class template Numeric_Limits in header file , which also defines some static member functions. Each function returns information of "Instantiating the Type of this template". That is, the information returned in Numeric_limits is about the information returned by the function in the type INT, Numeric_Limits is about type DOUBLE. Numeric_limits There is a function called min, MIN returns a minimum of "instantiated type", so Numeric_Limits ::min () returns to the minimum of the integer type. With Numeric_Limits (like other things in the standard library, Numeric_LIMITS exists in the namespace STD; Numeric_Limits itself is in the header file ), write PrintMinimumValue, you can easily:

Template Void PrintMinimumValue () {cout << std :: numeric_limits :: min ();

Numeric_Limits based approach to "Type-related constants" seems to be overhead, which is not. Because the length of the original code is not reflected in the generated target code. In fact, no instructions are generated at all calls to Numeric_LIMITS. Want to know what is going on, look at the following, this is a very simple implementation of numeric_limits :: min:

#include

Namespace std {

INLINE INT NUMERIC_LIMITS :: min () throw () {return INT_MIN;}

}

Because this function is declared as inline, it will be replaced by a function of its call (see Terms 33). It is just an int_min, that is, it is just a simple "constant defined constant". #Define. So even if the MAX function starting at this Territor seems to be called to each default parameter, it is only used to use another smart method to represent a type related constant (in this example INT_MIN). Some efficient and clever applications are all in C standard library, which can be referred to Terms 49.

Back to the MAX function: The most critical is that the MAX calculation is the same (very low) algorithm when the MAX calculation is calculated regardless of the number of parameters of the function. Which parameters don't care about anywhere in the function inside the function is "true", which is the default; and the default value selected is impossible to affect the correctness of the algorithm used. This is the reason why the use default parameter value is used.

For many functions, the right default is not found. For example, suppose you want to write a function to calculate the average of up to 5 INTs. You cannot use the default parameters, because the results of the function depends on the number of incoming parameters: If you pass 3 values, you must divide the total number of 3; if you pass 5 values, you must divide the total number 5. In addition, if the user does not provide a parameter, there is no "magical number" can be used as a default because all possible ints can be valid parameters. There is no choice if this case: must be overloaded:

Double AVG (INT A); Double AVG (Int A, Int B); Double AVG (Int A, Int B, INT C); Double AVG (Int A, Int B, INT C, INT D); Double AVG (INT A, INT B, INT C, INT D, INT E); Another case where the overload function is to complete a special task, but the algorithm depends on a given input value. This situation is very common for constructor: "Default" constructor constructs an object with air (no input), and the copy constructor is constructed according to an existing object:

// A class of Class Natural {public: natural (int initvalue); Natural (Const Natural & RHS);

PRIVATE: UNSIGNED INT VALUE

Void Init (INT INITVALUE); Void Error (Const String & MSG);

Inlinevoid Natural :: Init (int initvalue) {value = initValue;

Natural :: Natural (int initvalue) {if (initValue> 0) INIT (INITVALUE); Else Error ("Illegal Initial Value";}

INLINE NATURAL :: Natural (const natural); {..;}

The constructor input to the int is the error check, and the copy constructor does not need, so two different functions are required, which is overloaded. Also note that both functions must assign a new object. This will result in repetitive code in the two constructor, so you have to write a private member function init to solve this problem with the private member function init of "containing two constructor public code". This method - calls a "Overloaded Function" in the overload function - it is worth remembering because it is often useful (see clause 12).

转载请注明原文地址:https://www.9cbs.com/read-4458.html

New Post(0)