Help with try catch block

I wrote a small program but I am having problems getting my try catch block to work. Any help would be appreciated.

This is the exception file:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdexcept>

using namespace std;

class EmployeeIdNotInteger : public logic_error
{
public:

	EmployeeIdNotInteger()
		: logic_error("Empoyee number can only be a integer"){}

};


and this is the ccp file I am trying to use it:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <stdexcept>

#include "Lab_Nine.h"
#include "EmployeeIdNotInteger.h"

using namespace std;

//Constructor
Employee::Employee()
{
	setEmpId (empId);
	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);

}

//Setters
void Employee::setEmpId(int empId)
{
	try
	{
		newEmpId = empId;
	}
	catch(EmployeeIdNotInteger &employeeIdNotInteger)
	{
		cout << "Exception occurred: " << employeeIdNotInteger.what() << endl;
	}

}


void Employee::setFirstName( string name)
{
	if (name.length() <=10)
		firstName = name;
	else
	{
		firstName = name.substr(0,10);
	}

}


void Employee::setLastName( string last)
{
	if (last.length() <=20)
		lastname = last;
	else
	{
		lastname = last.substr(0,10);
	}
}

void Employee::setAge(int age)
{
	newAge = age;
}

void Employee::setSalary (double salary)
{
	newSalary = salary;
}


//Getters
int Employee::getEmpId()
{
	return newEmpId;
}

string Employee::getName()
{
	return firstName;
}

string Employee::getLast()
{
	return lastname;
}

int Employee::getAge()
{
	return newAge;
}

double Employee::getSalary()
{
	return newSalary;
}


my code works and I am able to create new employees but I can't get the catch block to pick up if I enter anything besides an integer.

Any advice?

Thanks,

Richard.
Last edited on
This is because you aren't throwing the exception, so the catch block never catchs it.
But there's something strange... empId is always an integer (because the function argument is a int type), so I think the exception will never raises.

You shold write the try block when you call setEmpId.
Like:

Employee::Employee()
{
try {
setEmpId (empId);
...
}
catch (EmployeeIdNotInteger &employeeIdNotInteger) {
...
}
setFirstName (name);
setLastName (last);
setAge (age);
setSalary (salary);

}
RKint,

thanks for the suggestion. I tried adding the try block to the employee constructor and still does not catch the error. I tried passing a double (10.2) and it returned 10. Then I tried passing a string and it returned the memory location.

Here is the code how it looks in the constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Employee::Employee()
{

	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);

	try
	{
		setEmpId (empId);
	}
	catch(EmployeeIdNotInteger &employeeIdNotInteger)
	{
		cout << "Exception occurred: " << employeeIdNotInteger.what() << endl;
	}

}


BTW, I do not get any errors while compiling or when running the program.
Last edited on
closed account (zb0S216C)
What are those variables you're passing to each method during the constructor?

rinnamorato wrote:
1
2
3
4
try
{
    newEmpId = empId;
}

This will not throw an exception, and as a result, the exception handlers are made redundant.

Is EmployeeIdNotInteger::what() even a member?

Wazzak
Last edited on
Framework,

I am not sure how to answer the question but those variables are suppose to be integers. They are defined to be int.

Here is the definition of the exception class:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdexcept>

using namespace std;

class EmployeeIdNotInteger : public logic_error
{
public:

	EmployeeIdNotInteger()
		: logic_error("Empoyee number can only be a integer"){}

};
closed account (zb0S216C)
rinnamorato wrote:
"Empoyee number can only be a integer"

This is where static_assert() shines:

1
2
3
4
5
6
7
8
9
10
#include <xtr1common>

template <typename id_type = int>
class EmployeeIdNotInteger : public logic_error
{
    static_assert(!std::tr1::is_integral<id_type>::value, 
                  "Empoyee number can only be a integer");

    EmployeeIdNotInteger();
};

Of course, static_assert() is a C++11 feature.

Wazzak
Last edited on
Framework,

I have not covered templates yet so I don't know how to implement the template and this is homework; therefore, I should use the conditions given.

The condition for this homework was pretty simple. It was to create a program and show how exceptions are implemented in constructors and how destructors destroy everything that was built before the exception was caught.

I am hoping I can work something out with this Employee class I used before and implement a try block for it.

Any other advice besides using a template?

Thanks,

Richard.
closed account (zb0S216C)
Then using throw() will suffice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
{
    A()
    {
        throw("Error");
    }
};

try
{
    A();
}

catch(const char *string)
{
    std::cout << "Caught: " << string << std::endl;
}

Can you integrate this into your program? I'm struggling to understand what you're asking.

Wazzak
I tried integrating the code into my program. This is what I have:

in the header file:
1
2
3
4
5
6
7
8
9
10
class EmployeeIdNotInteger 
{
public:

	EmployeeIdNotInteger()
	{
		throw("Error");
	}

};


and the constructor looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Employee::Employee()
{
	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);
	
	try
	{
		setEmpId (empId);	
	}
	catch(const char *string)
	{
		cout << "Caught: " << string << endl;
	}

}


I decided to add the try block directly into the constructor instead of using it in the setter. Before I made this changes, if I used the wrong parameters, the program would just return the wrong parameter as the employee number. I can't get it to return the string.
Last edited on
You could insist that employee IDs meet some totally arbitrary requirement, so you can then break the rule in your test. i.e. it must always be of the form 8nnn (n = 0..9), or must be even. I take it that any rule will do, as long as it triggers an exception? (If it has to be 4 digits long and begin with an 8, that gives you two possible errors!)

And I would throw one of the std::exceptions, or a derived class, as you're doing above, rather than a string or int.

Andy

P.S. what() is a member of std::exception
http://www.cplusplus.com/reference/std/exception/exception/
And logic_error's constructor allows you to specify the string what() should return.

Also, static_assert() is available pre-vc++11 : it's been part of Boost since ver 1.19.0 (10 Dec 2000)
Last edited on
Andy,

I was hoping that just by using a string instead of an integer it would throw an exception. I moved the try block directly into the constructor. This is the new constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Constructor
Employee::Employee()
{
	//setEmpId (empId);

	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);
	
	try
	{
		setEmpId (empId);	
	}
	catch(EmployeeIdNotInteger &employeeIdNotInteger )
	{
		cout << employeeIdNotInteger.what() << endl;

	}

}


I am hoping that once I catch the exception, the destructors would be called on the rest of the constructor. However, I am still unable to get it to fail. If it fails, it just returns the location number. My header is the same as above.

Any suggestions?
1
2
3
4
5
void Employee::setEmpId(empId){
  if( the_value_is_invalid(empid) )
    throw an_exception;
  empId_ = empId;
}
The constructor will throw the exception when invoking at setEmpId
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Employee::Employee() //if your constructor takes no parameters where the values come from...
Employee(int empId, string name, string last, int age, float salary)
{
	setEmpId (empId);
	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);
//if any of those setters fail, it will throw an exception
}

int main(){
try{
	Employee invalid(-1, "", "", 14, 1e12); 
}
catch(EmployeeIdNotInteger &employeeIdNotInteger)
{
	cerr << "Exception occurred: " << employeeIdNotInteger.what() << endl;
}
catch(...){
	cerr << "Unknow exception\n";
}
}


I can't get the catch block to pick up if I enter anything besides an integer.
Oh, but you aren't entering a non integer to the constructor, ¿are you?
Does your setEmpId still take an int? Passing a double to this function will just cause the compiler to truncate the number to an int automatically. Possibly with a cmpiler warning, but not a lot else.

If you modify the function do take a double, then you can use test it to see that the double passes has no decimal part.
ne555,

I am entering strings, doubles, and anything else that is not an integer but nothing passing to the catch block. I just did not post my testfile here. I am playing with your code right now and see what I can get out of it.
Andy,

yes, setEmpId takes an int. I figure that if I try to pass a double, the compiler was going to truncate the decimal. I am using a string to cause the fail. Here is what I am using as my test file:

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
int main(){

	
	//Variables
	string firstName;
	string lastName;
	int idNumber;

	Employee myWorker2;
	
	myWorker2.setLastName("Smith");
	myWorker2.setAge(34);
	myWorker2.setSalary(2600);

	cout << "Enter new Employee's ID number: " << endl;
	cin >> idNumber;

	cout << "Enter new Employee's name: " << endl;
	cin >> firstName;

	myWorker2.setFirstName(firstName);
	myWorker2.setEmpId(idNumber);
                myWorker2.printName();
}
Last edited on
While the compiler does automatically provide a "return 0;" if you forget it (just for main!), it's good form to end main() with return 0;

By the way, is your constructor still

1
2
3
4
5
6
7
8
9
Employee::Employee()
{
	setEmpId (empId);
	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);

}


It looks like it's calling set using the existing member variables. For the string members this is pointless: they will correctly zero themselves in their own constructors. For the ints it is setting them back to whatever random value they hold. It might be better to start off by zero-ing them? Similarly for the double.

1
2
3
4
Employee::Employee() : empId(0), age(0), salary(0.0)
{
	// name and last look after themselves
}



Ideally you would initialize (prob to zero) all non-class member variables in the constructor initializer list.
Last edited on
Thanks for the advice. I added the "Return 0;" to main().

I changed my constructor to include the try block for the empId. I was thinking that it would be easier to test for the value inside the constructor instead of the setter.

Here is what it looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Employee::Employee()
{
	//setEmpId (empId);

	setFirstName (name);
	setLastName (last);
	setAge (age);
	setSalary (salary);
	
	try
	{
		setEmpId (empId);	
	}
	catch(EmployeeIdNotInteger &employeeIdNotInteger )
	{
		cout << employeeIdNotInteger.what() << endl;

	}

}


I tried 0's out all the parameters and it gave me an error.
Topic archived. No new replies allowed.