void divisionbyzero::errormessage()
{
cout << "Division by zero is not allowed";
}
void divisionbyzero::logerror()
{
myfile.open("Example_10.4.txt", ios::app | ios::out);
myfile << "Division by zero error\n";
myfile.close();
}
void filenotfound::errormessage()
{
cout << "File not found";
}
void filenotfound::logerror()
{
myfile.open("Example_10.4.txt", ios::app | ios::out);
myfile << "File not found error\n";
myfile.close();
}
my source file is
//***********
//
// Example_10.4.cpp
// This program demonstrates exception handling with a class
// THIS PROGRAM WILL NOT COMPILE!!!
//
//************
include "Example_10.4.h"
include <iostream>
using namespace std;
divisionbyzero d;
int main()
{
float answer, dividend, divisor;
try
{
cout << endl << "Please enter a number: ";
cin >> dividend;
cout << "Please enter another number: ";
cin >> divisor;
This is an example out of a book that I am using to learn C++. The line 27 mentioned in the compiler error messages above is:
throw d;
This example is supposed to demonstrate throwing a class with exception handling. Can someone tell me what I am doing incorrectly here? From what I've seen, the code I typed in is exactly like the code in the book.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If you are referencing a book, you should at least tell us what the book is, otherwise there is little point in mentioning it! Besides that this example is so poor we need to know if only to avoid it!
I am not sure why, but the problem is solved by either moving the object "divisionbyzero d" into main() so that it is no longer statically allocated; or by removing the "fstream myfile" member and making it a variable local to the divisionbyzero::logerror() function. It is only accessed by that function in any case, so never needed to have class scope - that was just poor design. So although I am not certain why this problem arose, the problem is avoided altogether by good design practices (which it seems your book is not teaching!). I tried it in MSVC++ 2008, so it is not GCC specific - the MS error messages were even less helpful!
If that header file came from the book, throw the book away. Header files should not define code other than within the body of the class definition (inline functions), and should have include guards. It works now, but as soon as you have multiple compilation units using this header, it will fail. In this example the separate header is pointless in any case since there is only one compilation unit.
You can move the functions in the header either to the class body (inline) or to the .cpp file (or a spearate .cpp file, which in a real project would be preferable).
Moreover the "using" declaration should never be used in header files, and "using namespace std;" is just inviting problems - the std:: namespace is there for a reason, don't habitually circumvent it.
Do not put your projects in C:\Documents and Settings\Administrator\Desktop\ not all parts of the GNU tool chain work correctly with paths containing spaces.
The following code solves your problem, and most of the others I have mentioned:
The reason why the compiler complains about a private copy constructor is because C++ standard library streams cannot be copied. Since the exception class in this example contains a stream object by value and the class is used by value as well, the compiler must try to create a copy constructor and fails.
If the exception were caught by reference instead (which is better practice in any case), no copy would have had to be made of the exception object, the compiler wouldn't have tried to generate a copy constructor, and the code would compile.
I consider this a better way of throwing/handling exceptions:
Thanks for the help! You're right, the book I was using is prettry bad.
The book is entitled C++ Programming Fundamentals by Chuck Easttom.
I would not recommend this book to anyone.
I am now using Ivor Horton's Beginning Visual C++.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> The reason why the compiler complains about a private copy
> constructor is because C++ standard library streams cannot be copied.
Thanks for the clarification. I'd like to think that it would not have happened to me because I'd never have done such a thing in the first instance. As you say, and example of poor practice. I do not habitually use exceptions either; they are not always a good idea in embedded systems, which is what I work on.
> Ivor Horton's Beginning Visual C++.
From my experience, much better.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> I do not habitually use exceptions either; they are not always a good idea in embedded systems, which is what I work on.
I am in somewhat the same situation. I'm something you appear to loathe: a game programmer ;) When programming for limited devices such as the Nintendo DS, exceptions are a pretty bad idea too. So I avoid exceptions altogether, even for the more powerful systems such as Nintendo Wii, PC and the like (also helps maintain a shared codebase).
Paul
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am getting the following error messages:
My header file is
//
// Example_10.4.h
// Header file for Example_10.4.cpp
//
//************
include <iostream>
include <fstream>
using namespace std;
class divisionbyzero
{
private:
fstream myfile;
public:
void errormessage();
void logerror();
};
class filenotfound
{
private:
fstream myfile;
public:
void errormessage();
void logerror();
};
void divisionbyzero::errormessage()
{
cout << "Division by zero is not allowed";
}
void divisionbyzero::logerror()
{
myfile.open("Example_10.4.txt", ios::app | ios::out);
myfile << "Division by zero error\n";
myfile.close();
}
void filenotfound::errormessage()
{
cout << "File not found";
}
void filenotfound::logerror()
{
myfile.open("Example_10.4.txt", ios::app | ios::out);
myfile << "File not found error\n";
myfile.close();
}
my source file is
//***********
//
// Example_10.4.cpp
// This program demonstrates exception handling with a class
// THIS PROGRAM WILL NOT COMPILE!!!
//
//************
include "Example_10.4.h"
include <iostream>
using namespace std;
divisionbyzero d;
int main()
{
float answer, dividend, divisor;
try
{
cout << endl << "Please enter a number: ";
cin >> dividend;
cout << "Please enter another number: ";
cin >> divisor;
}
If you are referencing a book, you should at least tell us what the book is, otherwise there is little point in mentioning it! Besides that this example is so poor we need to know if only to avoid it!
I am not sure why, but the problem is solved by either moving the object "divisionbyzero d" into main() so that it is no longer statically allocated; or by removing the "fstream myfile" member and making it a variable local to the divisionbyzero::logerror() function. It is only accessed by that function in any case, so never needed to have class scope - that was just poor design. So although I am not certain why this problem arose, the problem is avoided altogether by good design practices (which it seems your book is not teaching!). I tried it in MSVC++ 2008, so it is not GCC specific - the MS error messages were even less helpful!
If that header file came from the book, throw the book away. Header files should not define code other than within the body of the class definition (inline functions), and should have include guards. It works now, but as soon as you have multiple compilation units using this header, it will fail. In this example the separate header is pointless in any case since there is only one compilation unit.
You can move the functions in the header either to the class body (inline) or to the .cpp file (or a spearate .cpp file, which in a real project would be preferable).
Moreover the "using" declaration should never be used in header files, and "using namespace std;" is just inviting problems - the std:: namespace is there for a reason, don't habitually circumvent it.
Do not put your projects in C:\Documents and Settings\Administrator\Desktop\ not all parts of the GNU tool chain work correctly with paths containing spaces.
The following code solves your problem, and most of the others I have mentioned:
//***********
//
// Example_10.4.h
// Header file for Example_10.4.cpp
//
//************
if !defined Example_10_4_h
define Example_10_4_h
class divisionbyzero
{
public:
void errormessage();
void logerror();
};
class filenotfound
{
public:
void errormessage();
void logerror();
};
endif // Example_10_4_h
//***********
//
// Example_10.4.cpp
// This program demonstrates exception handling with a class
//
//************
include "Example_10.4.h"
include <iostream>
include <fstream>
using std::cout ;
using std::cin ;
using std::endl ;
using std::ios ;
using std::fstream ;
divisionbyzero d;
int main()
{
float answer, dividend, divisor;
try
{
cout << endl << "Please enter a number: ";
cin >> dividend;
cout << "Please enter another number: ";
cin >> divisor;
}
void divisionbyzero::errormessage()
{
cout << "Division by zero is not allowed";
}
void divisionbyzero::logerror()
{
fstream myfile;
myfile.open("Example_10.4.txt", fstream::app | fstream::out);
myfile << "Division by zero error\n";
myfile.close();
}
void filenotfound::errormessage()
{
cout << "File not found";
}
void filenotfound::logerror()
{
std::fstream myfile;
myfile.open("Example_10.4.txt", fstream::app | fstream::out);
myfile << "File not found error\n";
myfile.close();
}
Clifford
The reason why the compiler complains about a private copy constructor is because C++ standard library streams cannot be copied. Since the exception class in this example contains a stream object by value and the class is used by value as well, the compiler must try to create a copy constructor and fails.
If the exception were caught by reference instead (which is better practice in any case), no copy would have had to be made of the exception object, the compiler wouldn't have tried to generate a copy constructor, and the code would compile.
I consider this a better way of throwing/handling exceptions:
try
{
// ...
throw divisionbyzero();
}
catch (const divisionbyzero& de)
{
de.errormessage();
de.logerror();
}
No ugly global variables, no copies made.
Paul
Thanks for the help! You're right, the book I was using is prettry bad.
The book is entitled C++ Programming Fundamentals by Chuck Easttom.
I would not recommend this book to anyone.
I am now using Ivor Horton's Beginning Visual C++.
> The reason why the compiler complains about a private copy
> constructor is because C++ standard library streams cannot be copied.
Thanks for the clarification. I'd like to think that it would not have happened to me because I'd never have done such a thing in the first instance. As you say, and example of poor practice. I do not habitually use exceptions either; they are not always a good idea in embedded systems, which is what I work on.
> Ivor Horton's Beginning Visual C++.
From my experience, much better.
Clifford
> I do not habitually use exceptions either; they are not always a good idea in embedded systems, which is what I work on.
I am in somewhat the same situation. I'm something you appear to loathe: a game programmer ;) When programming for limited devices such as the Nintendo DS, exceptions are a pretty bad idea too. So I avoid exceptions altogether, even for the more powerful systems such as Nintendo Wii, PC and the like (also helps maintain a shared codebase).
Paul