Exceptions thrown during initialization

Hello,

It's embarrassing how little I know about exceptions - in an attempt to get smart, I pose this question.

How exactly would one go about throwing an exception from an object's constructor?
Take a look at this snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <exception>

class ExceptionFoo : public std::exception {
	virtual const char* what() const throw() {
		return "ExceptionFoo occured!";
	}
};

class Foo {
public :
	Foo();
};

Foo::Foo() {
	if (true/*something bad happened!*/) {
		throw ExceptionFoo();
	}
}

int main(int argc, char* argv[]) {

	try {
		Foo foo;
	}
	catch (std::exception& exception) {
		std::cerr << exception.what() << std::endl;
	}

	std::cin.get();
	return 0;
}


There's some funny stuff going on. Object "foo" goes out of scope once the try block terminates, which (I would think) introduces undefined behavior in the catch block. Additionally, you cannot do anything with the object after the try-catch, because it doesn't exist.

Is something like this the proper way?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <exception>

class ExceptionFoo : public std::exception {
	virtual const char* what() const throw() {
		return "ExceptionFoo occured!";
	}
};

class Foo {
public :
	Foo() {}
	void init();//ugly

	bool m_bInit = false;//ugly
};

void Foo::init() {
	if (true/*something bad happened!*/) {
		throw ExceptionFoo();
	}
	else {
		m_bInit = true;
	}
}

int main(int argc, char* argv[]) {

	Foo foo;//ok

	try {
		foo.init();//ok
	}
	catch (std::exception& exception) {
		std::cerr << exception.what() << std::endl;
	}

	std::cin.get();
	return 0;
}
Last edited on
Is something like this the proper way?


No. If an exception is thrown in the constructor, it means the object has not been properly constructed and there is not a valid object to deal with. You had it right in the first snippet.
Thanks for the feedback cire, but then how can I make use of the object on line... let's say 29? If it ceases to exist after the try block, how can I do anything with it?
If it wasn't constructed correctly and isn't in a valid state, why would you want to do anything with it? If it was constructed correctly and is in a valid state, why would it throw an exception?
closed account (z05DSL3A)
1
2
3
4
5
6
7
8
9
10
11
12
Foo::Foo()
try
{
	if (true/*something bad happened!*/) {
		throw ExceptionFoo();
	}
}
catch(ExceptionFoo& )
{
    // clean up what you can and
    throw;
}
Better cope with errors without exceptions
If it wasn't constructed correctly and isn't in a valid state, why would you want to do anything with it? If it was constructed correctly and is in a valid state, why would it throw an exception?


Sorry if I didn't express myself correctly (or if I'm under a misapprehension).
What I mean is, regardless of whether or not the constructor throws an exception, I can't do anything with the object once it goes out of scope. I'm not saying that I would try to use the object while it's in a bad state - I mean, if the object was in a good state, I still wouldn't be able to use it, because it ceases to exist.

@Grey Wolf Thanks for the snippet I'll study this more.

@coder777 How do you mean?
The code that uses the object goes between the lines 24 and 25
@Cubbi, that changes my perception of exceptions entirely, which is exactly what I was hoping would happen. I knew there was a misunderstanding in my knowledge somewhere... thanks Cubbi!
Topic archived. No new replies allowed.