Exception thrown by the C ++ Constructor

Source: Internet
Author: User

Exception thrown by the constructor

1. the constructor defined in standard C ++ is a place where an object builds itself and allocates the required resources. Once the constructor is executed, it indicates that this object has been created, it has its own behavior and internal running status, and then the extinction process of objects (the execution of destructor ). But who can ensure that the object construction process will succeed? Maybe the current resource of the system is not enough, so that the object cannot fully build itself (all people are malformed, let alone others? Friends! Right !), So what method does it mean that the object fails to be constructed? C ++ programmers know that constructor in C ++ has no return value, so many books on C ++ programming come to the conclusion: "Because constructor has no return value, therefore, the only method for failing to construct the notification object is to throw an exception in the constructor ". The hero, a Yu, does not agree with this statement. Whoever says it doesn't trust evil! Although the C ++ Standard specifies that the constructor has no return value, we know that each function actually has a return value, which is saved in the eax register, therefore, there is actually a way to program the constructor to return a value to the upper-layer Object Creator. Of course, even if the constructor really does not have a return value, we can also know the state of the object construction process through a pointer type or reference type output parameter. Example:

Class mytest_base
{
Public:
Mytest_base (Int & Status)
{
// Do other job

// Object Construction failed due to insufficient resources
// Set status to 0 to notify the creator of the object
Status = 0;
}

Protected:
};

Void main ()
{
Int status;
Mytest_base obj1 (Status );

// Check whether object construction is successful
If (status = 0) cout <"Object Construction failed" <Endl;
}

The running result is:
An error occurred while building the object.
Yes! Do we still get the information about whether the object construction is successful or not? Do you think this is a problem? John, the hero, suggests that you stay here for a moment and think about the problem? OK! Maybe everyone knows the problem. Let's verify it!

Class mytest_base
{
Public:
Mytest_base (Int & Status)
{
// Do other job

// Object Construction failed due to insufficient resources
// Set status to 0 to notify the creator of the object
Status = 0;
}

Virtual ~ Mytest_base ()
{
Cout <"destroy an object of the mytest_base type" <Endl;
}

Protected:
};

Void main ()
{
Int status;
Mytest_base obj1 (Status );

// Check whether object construction is successful
If (status = 0) cout <"Object Construction failed" <Endl;
}

The running result is:
An error occurred while building the object.
Destroys an object of the mytest_base type.

Yes, the object's destructor is running, which conflicts with some of the object-oriented features specified in the C ++ standard. An object has not been constructed by itself. How can this problem be solved! It is like a dead malformed child that has not yet been born. Therefore, this method does not work. What should we do? That is, the last sentence in the above conclusion is correct. the only method for failing to construct the notification object is to throw an exception in the constructor, however, this is not because the constructor does not return values. On the contrary, the C ++ standard stipulates that the constructor does not return values because it is worried that it is likely to conflict with some object-oriented features, constructors cannot return values. (For personal understanding of the hero, you are welcome to discuss them ).

2. if an exception is thrown in the constructor, the object's destructor will not be executed. Haha ^-^, Ah Yu is very happy, look! Without the support of the C ++ Exception Handling Mechanism, object-oriented features in C ++ cannot be truly implemented, the C ++ standard does not mean that all objects must be constructed successfully! This is also too idealistic. Maybe it is only the day that the communist society has achieved (the CPU can be used at will, the memory can be used at will, and all the resources are yours !) It may be possible. The following is an example:

Class mytest_base
{
Public:
Mytest_base (string name = ""): m_name (name)
{
Throw STD: exception ("throwing an exception in the constructor, test !");
Cout <"constructs an object of the mytest_base type. The object name is:" <m_name <Endl;
}

Virtual ~ Mytest_base ()
{
Cout <"destroy an object of the mytest_base type with the object name:" <m_name <Endl;
}

Void func () Throw ()
{
Throw STD: exception ("intentionally throw an exception, test !");
}
Void other (){}

Protected:
String m_name;
};

Void main ()
{
Try
{
// An exception is thrown during object construction.
Mytest_base obj1 ("obj1 ");

Obj1.func ();
Obj1.other ();
}
Catch (STD: exception E)
{
Cout <E. What () <Endl;
}
Catch (...)
{
Cout <"unknow exception" <Endl;
}
}

The running result of the program will be verified: "if an exception is thrown in the constructor, the object's destructor will not be executed"

3. Is this the end of the discussion about how to handle exceptions thrown in Constructors? None! None! The hero Ai has further stories to tell! Let's look at a more complex example! As follows:

Class mytest_base
{
Public:
Mytest_base (string name = ""): m_name (name)
{
Cout <"constructs an object of the mytest_base type. The object name is:" <m_name <Endl;
}

Virtual ~ Mytest_base ()
{
Cout <"destroys an object of the mytest_base type. The object name is:" <m_name <Endl;
}

Void func () Throw ()
{
Throw STD: exception ("intentionally throw an exception, test! ");
}
Void other (){}

Protected:
String m_name;
};

Class mytest_parts
{
Public:
Mytest_parts ()
{
Cout <"construct an object of the mytest_parts type" <Endl;
}

Virtual ~ Mytest_parts ()
{
Cout <"destroy an object of the mytest_parts type" <Endl;
}
};

Class mytest_derive: Public mytest_base
{
Public:
Mytest_derive (string name = ""): m_component (), mytest_base (name)
{
Throw STD: exception ("an exception is thrown in the constructor of the mytest_derive object! ");

Cout <"constructs an object of the mytest_derive type. The object name is:" <m_name <Endl;
}

Virtual ~ Mytest_derive ()
{
Cout <"destroys an object of the mytest_derive type. The object name is:" <m_name <Endl;
}

Protected:
Mytest_parts m_component;
};

Void main ()
{
Try
{
// An exception is thrown during object construction.
Mytest_derive obj1 ("obj1 ");

Obj1.func ();
Obj1.other ();
}
Catch (STD: exception E)
{
Cout <E. What () <Endl;
}
Catch (...)
{
Cout <"unknow exception" <Endl;
}
}

The running result is:
Construct a mytest_base object named obj1
Construct a mytest_parts object
Destroys an object of the mytest_parts type.
Destroys a mytest_base object named obj1.
An exception is thrown in the constructor of the mytest_derive object!

In the above example, mytest_derive inherits from mytest_base, and mytest_derive also has a member variable of the mytest_parts type. When mytest_derive is constructed, an exception is thrown after mytest_base of the parent class has been constructed and m_component of the mytest_parts type has been constructed, this is called partial object construction. Yes, this is very common. objects are always inherited or aggregated. The object construction process is actually the construction process of all these sub-objects in the specified order, an exception occurred when constructing any child object in these processes. The object cannot say that it has completed all the construction processes. Therefore, there is a tricky problem, when partial object construction occurs, will the object be destructed? If so, how can we analyze the structure?

The following conclusions can be drawn from the running results:
(1) partial object construction is very common, and the occurrence points of exceptions are completely random. programmers should be careful when dealing with such situations;
(2) when an object is partially constructed, the constructed sub-objects are parsed in reverse order (that is, the object before the exception occurrence point ); the sub-object that has not yet started construction will not be constructed (that is, the object after the exception occurrence point), and of course there will be no destructor; the sub-objects being built and the object itself will stop building (that is, the object with exceptions), and its structure will not be executed.

General summary when an exception is thrown in the constructor
(1) In C ++, the only way to notify the object construction failure is to throw an exception in the constructor;
(2) If an exception is thrown in the constructor, the object's destructor will not be executed;
(3) when an object is partially constructed, the constructed sub-objects are parsed in reverse order;
(4) Haha ^-^, is it that sentence? "C ++ Exception Handling will not destroy any object-oriented feature !", Therefore, the hero, a Yu, once again suggested that you remember this article!

Related Article

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.