The difference between the passing of c ++ exception parameters and the passing of common function parameters ., Function Parameters
In terms of syntax, declared parameters in a function are the same as those declared in a catch clause. Parameters in a catch can be value type, reference type, or pointer type. For example:
Try
{
.....
}
Catch (A)
{
}
Catch (B & B)
{
}
Catch (C * c)
{
}
Although they are the same on the surface, the compiler processes the two very differently. When a function is called, the control of the program is finally returned to the function call. However, when an exception is thrown, the control will never return to the place where the exception is thrown.
Class;
Void func_throw ()
{
A;
Throw a; // throw a copy of a and copy it to a temporary object.
}
Try
{
Func_throw ();
}
Catch (A a) // copy of A temporary object
{
}
When an exception object is thrown, a copy of the exception object is thrown. When an exception object is copied, the copy operation is completed by the object's copy constructor. This copy constructor is the copy constructor of the class corresponding to the static type of the object, rather than the copy constructor of the class corresponding to the dynamic type of the object (dynamic type. In this case, the object will lose the RTTI information.
An exception is a copy of another object. This fact affects how you can throw another exception in the catch Block. For example, the following two catch blocks are the same at first glance:
Catch (A & w) // catch an exception
{
// Handle exceptions
Throw; // throw an exception again and let it continue to pass
}
Catch (A & w) // catch A Widget exception
{
// Handle exceptions
Throw w; // pass the copy of the caught exception
}
The current exception is thrown again in the first block, no matter what type it is. (It may be A derived class of)
The second catch Block throws a new exception and loses the original type information.
In general, you should use throw to throw the current exception again, because it will not change the exception type passed out, and is more efficient, because there is no need to generate a new copy.
Take a look at the following three statements:
Catch (A w)... // pass the value
Catch (A & w)... // pass the reference
Catch (const A & w)... // const reference
An object thrown by an exception (always a temporary object) can be captured through a common reference; it does not need to be captured by referencing to a const object. A temporary object cannot be transferred to a non-const reference type parameter in a function call, but it is allowed in an exception. // Because the temporary object will be released later, the non-const reference in the function will reference a non-existing object.
Return to the abnormal object copy. We know that when passing function parameters by passing values, we create a copy of The passed object and store the copy to the function parameters. Similarly, when we pass an exception by passing the value, this is also done when we declare a catch clause as follows:
Catch (A w)... // capture by passing values
Two copies of the thrown objects will be created. One is a temporary object that must be created for all exceptions, and the other is to copy the temporary object to w. In fact, the compiler will optimize a copy. Similarly, when we capture exceptions through reference,
Catch (A & w)... // catch by reference
Catch (const A & w)... // const reference capture
This will still create a copy of The thrown object: copy is a temporary object. On the contrary, when we pass function parameters through references, no object is copied. But not all compilers do. VS200 is very strange.
The exception thrown by pointer is the same as the parameter passed by pointer. Either method is a copy of the pointer to be passed. You cannot think that the thrown pointer is a pointer to a local object, because the local variable has been released when the exception leaves the living space of the local variable. The Catch clause returns a pointer to an object that does not exist. This behavior should be avoided during design.
Another important difference is that the process of type matching between the function caller or the thrown exception and the called or caught exception is different. When a function passes a parameter, if the parameter does not match, the compiler will try a type conversion, if any. This is not the case for exception handling. See the example below:
Void func_throw ()
{
CString;
Throw a; // throw a copy of a and copy it to a temporary object.
}
Try
{
Func_throw ();
}
Catch (const char * s)
{
}
CString is thrown. If const char * is used for capturing, this exception cannot be caught.
However, two types of conversions can be performed during exception matching in the catch clause. The first is the conversion between the base class and the derived class. A catch clause used to capture the base class is also
Can handle exceptions of the derived class type. In turn, it is used to capture exceptions of the base class that cannot be captured by the derived class.
The second is to allow the conversion from a typed pointer to an untyped pointer, so the catch clause with the const void * pointer can catch any type of pointer type exception:
Catch (const void *)... // catch all pointer exceptions
In addition, you can use catch (...) to catch all exceptions. Note that there are three points.
The last difference between passing parameters and passing exceptions is that the matching order of catch clauses always depends on the order in which they appear in the program. Therefore, an exception in a derived class may occur
Catch clause capture for its base class exceptions. This is called exception interception. Generally, the compiler has a warning.
Class {
Public:
A ()
{
Cout <"class A creates" <endl;
}
Void print ()
{
Cout <"A" <endl;
}
~ A ()
{
Cout <"class A destruct" <endl;
}
};
Class B: public
{
Public:
B ()
{
Cout <"class B create" <endl;
}
Void print ()
{
Cout <"B" <endl;
}
~ B ()
{
Cout <"class B destruct" <endl;
}
};
Void func ()
{
B B;
Throw B;
}
Try
{
Func ();
}
Catch (B & B) // you must put B in front. If A and B are put in front of B, the exception of type B is intercepted first.
{
B. print ();
}
Catch (A &)
{
A. print ();
}
On the contrary, when you call a virtual function, the called function is located in the closest dynamic type (dynamic type) to the object that calls the function.
Class. You can say that virtual function matching adopts the optimal matching method, while Exception Processing and matching adopts the first matching method.
A temporary object cannot be transferred to a non-const reference type parameter in a function call, but it is allowed in an exception. // Because the temporary object will be released later, the non-const reference in the function will reference a non-existing object. When it is a const reference type, the temporary object will not be released for a while, but will be the same as the lifecycle of the parameter in the function, so that the temporary object can be referenced.
Class
{
Public:
A ()
{
M_Int = 10;
}
Public:
Int m_Int;
};
A GetInt ()
{
A;
Return;
}
Void Test (A & pA)
{
Cout <pA. m_Int <endl; // 10 return is also output;
}
Int main ()
{
A & pA = GetInt ();
Cout <pA. m_Int <endl; // 10 can be output because pA is a reference and the temporary variables returned by GetInt are not released immediately. The lifecycle is consistent with that returned by pA.
Test (GetInt (); // It is not a temporary variable passed to a parameter not referenced by the const. How can this problem be solved?
System ("pause ");
Return 1;
}