Menu

Dev-C++ Exception Handling Compilation Errors

2009-05-07
2012-09-26
  • Euclide Legnon

    Euclide Legnon - 2009-05-07

    I am getting the following error messages:

     In copy constructor `std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char,   
     738 C:\Dev-Cpp\include\c++\3.4.2\bits\ios_base.h `std::ios_base::ios_base(const std::ios_base&)' is private   
                                                                                                                          std::char_traits<char> >&)': 
     27 C:\Documents and Settings\Administrator\Desktop\Source_Code\Example_10.4.cpp within this context.
     27 C:\Documents and Settings\Administrator\Desktop\Source_Code\Example_10.4.cpp In copy constructor     
    `std::basic_filebuf<char, std::char_traits<char> >::basic_filebuf(const std::basic_filebuf<char, std::char_traits<char> >&)': 
     769 C:\Dev-Cpp\include\c++\3.4.2\streambuf `std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const 
     std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>]' is private 
     27 C:\Documents and Settings\Administrator\Desktop\Source_Code\Example_10.4.cpp within this context
    

    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(divisor == 0)
        {
           throw d;
        }
           answer = dividend / divisor;
           cout &lt;&lt; endl &lt;&lt; &quot;The answer is &quot; &lt;&lt; answer &lt;&lt; endl;
    }
    catch(divisionbyzero de)
    {
       de.errormessage();
       de.logerror(); 
    }
    
    return 0;
    

    }


    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.
    
     
    • cpns

      cpns - 2009-05-07

      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;

          if(divisor == 0) 
          { 
              throw d ; 
          } 
          answer = dividend / divisor; 
          cout &lt;&lt; endl &lt;&lt; &quot;The answer is &quot; &lt;&lt; answer &lt;&lt; endl; 
      } 
      catch(divisionbyzero de) 
      { 
          de.errormessage(); 
          de.logerror();  
      }
      
      return 0;
      

      }

      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

       
      • Paul van Zelst

        Paul van Zelst - 2009-05-08

        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

         
    • Euclide Legnon

      Euclide Legnon - 2009-05-08

      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++.

       
    • cpns

      cpns - 2009-05-08

      > 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

       
      • Paul van Zelst

        Paul van Zelst - 2009-05-08

        > 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

         

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.