Exercise caution when selecting between function overload and default parameter values

Source: Internet
Author: User

--------------------------------------------------------------------------------
 

Clause 24: exercise caution when selecting between function overload and default parameter values

The reason for obfuscation between function overloading and Setting Parameter defaults is that they allow a function to be called in multiple 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
// Default parameter value
G (); // call G (0)
G (10); // call G (10)
So when should we use this method?
The answer depends on the other two questions. First, is there a value that can be used as the default value? Second, how many algorithms are used? Generally, if you can select an appropriate default value and only use an algorithm, use the default parameter (see article 38 ). Otherwise, function Overloading is used.
The following is a function that can calculate the maximum value of up to five int values. This function uses -- take a deep breath to see clearly -- STD: numeric_limits <int >:: min (), as the default parameter value. I will introduce this value later. The code of the function is provided here:
Int max (int,
Int B = STD: numeric_limits: 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;
}

Now you can relax. STD: numeric_limits <int>: min () is something that has been defined in C in the C ++ standard library using a unique new method, that is, in <limits. h> the int_min macro defined in -- the minimum possible value of the int generated by the compiler that processes your c ++ source code. Yes, its syntax deviates from the conciseness of C, but behind those colons and other strange syntaxes it makes sense.
Assume that you want to write a function template with a fixed number type parameter. The function generated by the template can print the minimum value represented by the "instantiation type. This template can be written as follows:
Template
Void printminimumvalue ()
{
Cout <indicates the minimum value of the T type;
}

If you only use <limits. h> and <float. h> it is very difficult to write this function. Because I don't know what t is, I don't know whether to print int_min, dbl_min, or other types of values.
To avoid these difficulties, the standard C ++ Library (see article 49) is in the header file <limits>
Defines a class template numeric_limits, which also defines some static member functions. Each function returns the information of "instantiating the template type. That is to say, the information returned by the function in numeric_limits <int> is about the int type, numeric_limits <double>
The information returned by the function is of the double type. Numeric_limits has a function called Min. Min returns the minimum value that can be expressed as "instantiation type". Therefore, numeric_limits <int >:: min () returns the minimum value 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 <limits>), printminimumvalue can be easily written as follows:
Template
Void printminimumvalue ()
{
Cout <STD: numeric_limits: min ();
}

The numeric_limits-based method is used to indicate "type-related constants", which seems to be costly. Because the lengthy statements of the original code are not reflected in the generated target code. In fact, calls to numeric_limits do not generate any command at all. If you want to know what is going on, take a look at the following. This is a very simple implementation of numeric_limits <int>: min:
# Include
Namespace STD {
Inline int numeric_limits <int>: min () Throw ()
{Return int_min ;}
}

Because this function is declared as inline, its call will be replaced by the function body (see section 33 ). It is only int_min, that is, it is only a simple # define of "constants defined during implementation. So even if the max function at the beginning of the terms looks like a function call to each default parameter, in fact, it only uses another smart method to represent a type-related constant (in this example, the constant value is int_min ). Some Efficient and clever applications like this are found in the C ++ standard library, which can be referred to article 49.
Return to the max function: the most important thing is that, no matter how many parameters the function caller provides, Max uses the same (very inefficient) algorithm for calculation. In a function, you do not need to care about which parameters are "true" and which are default values. In addition, the selected default values cannot affect the correctness of the algorithm calculation. This is why the default parameter value scheme is feasible.
For many functions, the appropriate default value is not found. For example, if you want to write a function to calculate the average value of up to five int values. The default parameter cannot be used here, because the result of the function depends on the number of input parameters: If three values are input, the total number is divided by 3. If five values are input, divide the total number by 5. In addition, if the user does not provide a parameter, no "magic number" can be used as the default value, because all possible int values can be valid parameters. In this case, you have no choice but to reload the function:
Double AVG (int );
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 scenario where you must use overload functions is that you want to complete a special task, but the algorithm depends on the given input value. This is common for constructors: the "default" constructor creates an object out of thin air (without input), and the copy constructor constructs an object based on an existing object:
// A class that represents a natural number
Class natural {
Public:
Natural (INT initvalue );
Natural (const natural & RHs );
 
PRIVATE:
Unsigned int value;
 
Void Init (INT initvalue );
Void error (const string & MSG );
};

Inline
Void 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 & X)
{Init (X. Value );}

The constructor whose input is int must perform an error check, but the copy constructor does not need to. Therefore, two different functions are required for implementation. This is the overload. Note that both functions must assign an initial value to the new object. This leads to duplicate code in two constructors. Therefore, you need to write a private member function init that contains the public code of two constructors to solve this problem. This method-call a public underlying function in a overload function-it is worth remembering because it is often useful (see clause 12 ).

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.