Dialogue # 27: Baseless Exceptions

zhaozj2021-02-16  52

(WQ: This article has been translated on 9CBS, but it can't find it for a while, it will also translate it.)

Dialogue # 27: Baseless Exceptions

"Well, yes, yes," I feel good yourself. "It seems that I found a compiler error."

I am tracking a fault, there is an exception that is not captured by an exception handling system. The streamlined code is as follows:

Class Base

{

// ...

WhatVER ...

}

Class Derived: Private Base

{

Void f () {

Try {

Throw derived ();

}

Catch (Base &) {

COUT << "caught base" << endl;

}

Catch (...)

{

COUT << "caes" else "<< endl;

}

}

}

I expect that the program implicitly converts the DeriveD object to Base &, so it will print "capture Base". However, in fact, it has no conversion to print out "Caught Something Else". When I was confused from the mistake of the compiler, I remember the teacher's teaching: "Remember, apprentice, never assume any of you or the compiler is correct. Always check the sacred standard to determine your understanding And wisdom. "After a few minutes, my selfishness has changed to confuse, because the standard said that the compiler behavior is correct:

A capture program matches the object of the type E, the condition is ... The parameter type of the capture program is CV T or CV T & and T is a no-sense public base class ... [1]

Unseason public base class? Ok, this is some unreasonable, I think. After all, that derived is converted to the Base object because it is in your own code space. In order to test this problem, I added a statement before trying.

Base & testRef = * this;

Affirmation, it has no compilation problem.

"You look very confused, apprentice." I screamed. I don't think I will get used to the sudden appearance of Guru.

"Well, yes," I muttered. "I don't understand why the standard is not allowed to be converted by type, and it is allowed in the code."

She carefully wrote in the "brick" in the "brick". "In the statement 'base & testref = * this;' The type conversion occurs on ', when is the compiler check whether the conversion is allowed, and depending on access rights or inheritance?"

"Well, when it constructs this quote, it checks. No, wait - wrong. It is compiled."

"Correct, child. Next, when is the compiler to check the type conversion of an abnormal capture program?"

"It also happened in the compile period, isn't it?" Guru didn't answer. In fact, she is raising her eyebrows, staring at me with gray eyes - this is her "What are you sure?". I have thought about it for a while. Then understand. "Oh, of course," I said. "Assessment occurs during the runtime. Any type of object can be thrown, so the exception capture program must view the type of actual object."

"Where is access to where information is stored in operation?" GURU prompts.

"It is stored in ..." I stopped. "Hey, this is a trap - access check should be performed during the compile period, no time period information. Ah, I understand now - there is a limit for the lack of access to the information." I thought Guru at this time . However, she didn't. She just stood quietly next to my compartment. I thought again.

"Wait a minute," I said slowly. "No, I still don't understand. The program must still know whether there is a public base class with no sense for conversion. What happens ..." I turned to the whiteboard, wrote a more complicated example:

#include

Using namespace std;

Class Base

{

PUBLIC:

Virtual ~ base () {}

}

Class DerivedPriVately: Private Base

{

// ...

WhatVER ...

}

Class DerivedPublicly: Public Base

{

// ...

WhatVER ...

}

Void G (int which)

{

IF (Which <0) throw derivedpublicly ();

Else if (Which == 0) throw base ();

Else throw derivedpriVately ();

}

Void f (int value)

{

Try {

g (value);

}

Catch (Base &)

{

COUT << "caught base" << endl;

}

Catch (...)

{

COUT << "caes" else "<< endl;

}

}

int main ()

{

f (-1);

f (0);

f (1);

}

"If I correctly understand the standard, the output of the first two calls should be 'caught base', the last one is 'caupht something else'. The compiler obviously did a certain period of time check, so defined it is public. Base class? "

"Ah, child, if you modify the privately born class, add a Friend Void F (int); statement. Then you expect what will happen?"

"Well, the derivedprodely object has declared F () as a friend, so I expect it to print the 'caught base'."

She smiled. "Now, what information does the program need to know that type conversion is acceptable?"

What is the distress of the guru's Socratic method? I thought. "Well," I am trying to try, "Obviously, it must track inheritance tree. And, I guess it must track friends. This should be very easy, though - as long as it is generated in the OBJ file in F () Program. "

"Ah, but if f () doesn't know how it is DeriveDPRIVATELY CII? That is, F () The compilation unit only references Base, it does not contain the header file of the declarative derivedprodely. No, my child Information must be stored globally, and the program needs to map a specific machine code to a specific function to decide whether a function is executed as a friend. In the complex system level, there may be any friend or implicit type Conversion order, maintaining this information will be a major overhead, but it may not be necessary. Maintaining a list of public base classes with a unspeakable public base class is simple. "

"By the way, you will notice that the same restrictions apply to the case of capturing pointers. The compiler will only point a pointer to point to the pointer to the type of non-sense, the pointer does have additional Ability to perform restricted conversion. "Guru turned away. "The solution is to look clear, apprentice. By the way, the sacred standard requires only two places to check the inspection of the period of time, and the abnormal capture is one of them. The other is of course ..." but she turned The bend, so I didn't listen to the rest of the rest.

Of course, the GURU is correct. The solution is simple: add an exception capture for Derived:

Class Derived: Private Base

{

Void f () {

Try {

Throw derived ();

}

Catch (Derived &) {

Cout << "caughter" << Endl;

}

Catch (Base &) {

COUT << "caught base" << endl;

}

Catch (...) {

COUT << "caes" else "<< endl;

}

}

}

[Note]

[1] ISO C Standard, CLAUSE 15.3 Paragraph 3.

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

New Post(0)