answersLogoWhite

0


Best Answer

Before we look at how to handle an exception in a derived class, it is important that you understand what happens when an exception is thrown. As soon as an exception is thrown, the call stack immediately unwinds until a suitable handler for the exception is found. If no handler is found and the call stack is completely unwound back to the main function, the application terminates with an unhandled exception.

By way of an example, consider the following:

#include<iostream>

#include<exception>

#include<memory>

struct A {

A () { std::cout << "Construct\tA\n"; }

~A () { std::cout << "Destruct\tA\n"; }

virtual void do_something(int i) = 0;

};

struct B : A {

B () { std::cout << "Construct\tB\n"; }

~B () { std::cout << "Destruct\tB\n"; }

void do_something(int i) override;

};

void B::do_something (int i)

{

std::cout << "Begin B::do_something(" << i << ")\n"; if (!i)

throw std::range_error ("B::do_something(int) : argument must be non-zero!");

std::cout << "End B::do_something(" << i << ")\n";

}

void caller()

{

std::cout << "Begin caller()\n";

B* b = new B;

for (int i=-5; i<=5; ++i)

b->do_something (i);

delete b;

std::cout << "End caller()\n";

}

int main()

{

std::cout << "Begin main()\n";

caller();

std::cout << "End main()\n";

}

When you execute this code, you will see the following output:

Begin main()

Begin caller()

Construct A

Construct B

Begin B::do_something(-5)

End B::do_something(-5)

Begin B::do_something(-4)

End B::do_something(-4)

Begin B::do_something(-3)

End B::do_something(-3)

Begin B::do_something(-2)

End B::do_something(-2)

Begin B::do_something(-1)

End B::do_something(-1)

Begin B::do_something(0)

The program terminates at this point with an unhandled exception. The trace code obviously gives us an idea of where the exception occurred however the purpose of the trace code is not to track down the problem, it is merely to highlight the flow of execution (in real code we may not have access to any trace code at all).

If we place a catch-all exception handler in main(), we can get a better idea of what the problem is:

int main()

{

std::cout << "Begin main()\n";

try

{

caller();

}

catch (...) // catch-all

{

try

{

std::exception_ptr eptr = std::current_exception();

std::rethrow_exception (eptr);

}

catch (const std::exception& e)

{

std::cerr << "Exception: " << e.what() << "\n";

}

}

std::cout << "End main()\n";

}

Note the use of a nested try-catch in the catch-all. This is required because we have no way of knowing what type of exception we're actually dealing with in the catch-all. We first obtain an exception pointer to the current exception and then re-throw that pointer. This creates a standard exception which we can catch and handle normally.

Now we get the following output:

Begin main()

Begin caller()

Construct A

Construct B

Begin B::do_something(-5)

End B::do_something(-5)

Begin B::do_something(-4)

End B::do_something(-4)

Begin B::do_something(-3)

End B::do_something(-3)

Begin B::do_something(-2)

End B::do_something(-2)

Begin B::do_something(-1)

End B::do_something(-1)

Begin B::do_something(0)

Exception: B::do_something(int) : argument must be non-zero!

End main()

The program appears to exit normally so you might think that we could feasibly keep this program running now that we've handled the exception. But we cannot. We haven't actually handled the exception at all we've simply logged the problem at this stage.

From the trace output we can see that derived object B was constructed, but it was not destroyed. More importantly, the pointer we used to construct that object no longer exists: it was local to the caller() function and that fell from scope the moment we entered the catch-all in main(). The pointer is gone but the B object it pointed to still exists in memory (as does its base class A). in other words, we've created a resource leak.

If nothing else, this example should demonstrate quite clearly why we must never use raw pointers to dynamically allocated memory in C++. Even though we have a catch-all in main(), we have no way to recover resources allocated between main() and the point at which the exception was thrown, so the only option is to exit the program at this point.

The best way to avoid leaked resources is to use a resource handle instead of raw pointers. That is, if we use a statically-allocated object that encapsulates a raw pointer, we get the benefit of dynamic allocation and automatic recovery in the event of an exception. Consider the following alternative implementation of our caller() function:

void caller()

{

std::cout << "Begin caller()\n";

std::unique_ptr<B> b {new B};

for (int i=-5; i<=5; ++i)

b->do_something (i);

std::cout << "End caller()\n";

}

The std::unique_ptr class is a smart pointer. It behaves just like a raw pointer but we no longer need to explicitly delete the pointer; the smart pointer does that for us automatically as soon as it falls from scope. Indeed, if we try to explicitly delete a smart pointer, we'd get a compiler error. Remember that a smart pointer is not a pointer at all, it just behaves like one.

If we run the program again, we see the following output:

Begin main()

Begin caller()

Construct A

Construct B

Begin B::do_something(-5)

End B::do_something(-5)

Begin B::do_something(-4)

End B::do_something(-4)

Begin B::do_something(-3)

End B::do_something(-3)

Begin B::do_something(-2)

End B::do_something(-2)

Begin B::do_something(-1)

End B::do_something(-1)

Begin B::do_something(0)

Destruct B

Destruct A

Exception: B::do_something(int) : argument must be non-zero!

End main()

As you can see, our B object now destroys itself automatically (along with the base class A). Now we're in a better position to make a full recovery from the exception and deal with it properly.

User Avatar

Wiki User

9y ago
This answer is:
User Avatar

Add your answer:

Earn +20 pts
Q: How to handle derived class exception in c plus plus?
Write your answer...
Submit
Still have questions?
magnify glass
imp
Continue Learning about Engineering

What is single inheritance in c plus plus?

Multiple inheritance occurs when a class is derived directly from two or more base classes. class b1 {}; class b2 {}; class d: public b1, public b2 {}; // multiple inheritance class


What is multilevel inheritance in C plus plus?

Multi-level inheritance involves at least 3 classes, a, b and c, such that a is derived from b, and b is derived from c. c is therefore the least-derived base class, b is an intermediate base class and a is the most-derived class.


What is the order of construction and destruction in c plus plus?

The least-derived base classes are always constructed first, in the order specified by the derived class inheritance list. The most-derived class (the one you are actually instantiating) is always constructed last. Destruction is basically the reverse of construction. However, base class destructors must be declared virtual to ensure that the most-derived class destructor is called first, regardless of which class destructor is actually invoked. That is, if you hold a pointer to a base class that has no virtual destructor, deleting that pointer will only destroy the base class, not the derived class, leaving the derived class in an invalid state (because it no longer has an underlying base class) and with no way to recover the memory it consumes. It is important to remember that if you declare any virtual methods within a class, you must also declare the destructor virtual. A class without a virtual destructor is not intended to be derived from. If it has virtual methods, but no virtual destructor, it is not well-formed and must not be used as a base class.


What is a virtual base class in C plus plus when the different methods in base and derived classes have the same name true or false?

False. A virtual base class is one that is common to two or more derived classes that are themselves base classes, and that may be combined through multiple inheritance. By declaring the common base class to be virtual in its direct derivatives, only one instance of the common base class exists in the multiple-inheritance classes.


How do you implement inheritance in c plus plus?

You implement inheritance by deriving a new class of object from an existing class of object. The existing class is known as the base class of the derived class.Classes declared final cannot be used as bases classes and classes without a virtual destructor (or a virtual destructor override) cannot be used as polymorphic base classes.

Related questions

Can a c plus plus class be derived from a Java class?

No.


What is single inheritance in c plus plus?

Multiple inheritance occurs when a class is derived directly from two or more base classes. class b1 {}; class b2 {}; class d: public b1, public b2 {}; // multiple inheritance class


Write a c plus plus programme to illustrate single inheritance?

struct A {}; // base class struct B : A {} // derived class (single inheritance).


What is meant by inheritance in c plus plus language?

Inheritance in C++ and in other Object Oriented languages is the creation of a class that incorporates a different class. The child (or derived) class "inherits" all of the elements (attributes and methods) of the parent (or base) class. Depending on the design of the base class, the derived class can use methods and attributes of the base class as if they were its own. Typically, however, attributes of the base class are private to the base class and inaccessible to the derived class so as to maintain class hierarchy and data encapsulation.


What is private specifier in c plus plus?

The private specifier states that the member can only be accessed by the containing class, and not by any derived class, nor by any other code outside of a class.


What are Public and Private inheritance in c plus plus?

Public, protected and private inheritance determine how the public and protected base class members are inherited by the derived class. Private members are never inherited and are therefore unaffected by the type of inheritance (they remain private to the base class). The following table summarises how inheritance affects accessibility of base class members with respect to the derived class: public inheritanceprotected inheritanceprivate inheritancepublic member of base classpublic member of derived classprotected member of derived classprivate member of derived classprotected member of base classprotected member of derived classprotected member of derived classprivate member of derived classprivate member of base classprivate member of base classprivate member of base classprivate member of base class Note that accessibility to individual public and protected base class members can be overridden within the derived class, regardless of the type of inheritance specified.


Represent a stack in c plus plus?

Use a vector with a base class type. Any objects derived from the base class can be pushed and popped from the vector just as you would from a stack.


What is multilevel inheritance in C plus plus?

Multi-level inheritance involves at least 3 classes, a, b and c, such that a is derived from b, and b is derived from c. c is therefore the least-derived base class, b is an intermediate base class and a is the most-derived class.


When you define a c plus plus class what items are considered part of the interface?

The interface of a C++ class is the public methods and attributes that are exposed by the class. In a pure abstract base class, the interface is enforced by the compiler in each of the derived child classes.


What is the order of construction and destruction in c plus plus?

The least-derived base classes are always constructed first, in the order specified by the derived class inheritance list. The most-derived class (the one you are actually instantiating) is always constructed last. Destruction is basically the reverse of construction. However, base class destructors must be declared virtual to ensure that the most-derived class destructor is called first, regardless of which class destructor is actually invoked. That is, if you hold a pointer to a base class that has no virtual destructor, deleting that pointer will only destroy the base class, not the derived class, leaving the derived class in an invalid state (because it no longer has an underlying base class) and with no way to recover the memory it consumes. It is important to remember that if you declare any virtual methods within a class, you must also declare the destructor virtual. A class without a virtual destructor is not intended to be derived from. If it has virtual methods, but no virtual destructor, it is not well-formed and must not be used as a base class.


In c plus plus what are the three ways that classes can relate to each other?

Class wrappers (embedded objects), inheritance (derived objects) and friend classes.


Different access specifies in C plus plus?

Public members and methods of a class are universally accessible. Protected members and methods of a class are accessible to methods of instances of that class and its derived classes. Private members and methods of a class are accessible only to methods of instances of that class.Class A has three members: public_member, protected_member, and private_member, which have access corresponding to their names. Class A has access to all three. Class B, derived from class A, has access to public_member and protected_member, but not private_member. Unrelated class C has access only to public_member.