C++ Exceptions Throw Empty Class

3.6k views Asked by At

Below is an excerpt from "Programming: Principles and Practice Using C++". I'm confused by the throw Bad_area() notation. The book tries to explain it, "Bad_area() means 'Make an object of type Bad_area'," continuing with that it then throws that type. This explanation is not congruent with the assignment notation, eg. int x=1 == int x(1); or Bad_area x;.

Example code (commented out the try-block):

class Bad_area {}; // a type specifically for reporting errors from area()

// calculate area of a rectangle
// throw a Bad_area exception in case of a bad argument
int area(int length, int width)
{
  if (length<=0 || width<=0) throw Bad_area();
  return length*width;
}

int main()
try {
  // ...
}
catch (Bad_area) {
  cout << "Oop! bad arguments to area()\n";
}
1

There are 1 answers

4
Manu343726 On BEST ANSWER

Bad_area() is a explicit call to the default constructor of the class Bad_area.
That is, what throw Bad_area() does is to return (throw) directly an anonimus instance of the class Bad_area.

Is the same as in OO languages like Java or C#, when you return a instance directly. For example:

void foo() throws MyException
{
    if( error ) throw new MyException();
}

Note that that explicit calls to constructors are rarelly used in C++, because the lifetime of the instances is based on RAII.
There are only a few cases where a explicit call is a good idea, most of them are like your example, return statements. For example a point_2d class wich algebraic methods are easilly inlined:

struct point_2d
{
    float x;
    float y;

    point_2d(float _x = 0.0f , float _y = 0.0f) : x( _x ) , y( _y ) {}

    //Easy inlineable addition:
    point_2d operator+(const point_2d& lhs , const point_2d& rhs)
    {
        return point_2d{ lhs.x + rhs.x , lhs.y + rhs.y };
    } 
};

On the other hand, execpt that exceptional cases, direct calls to constructors must be avoided. Its common to see newebbies C++ code with a Java style. For example:

int main()
{
    point_2d* point = new point_2d( 10.0f , 10.0f ); //Ok, this is not exactly a call to
                                                     //to the ctor, but has the same meaning.
                                                     //WTF why you use dynamic memory here?
}

Or a correct C++ variable declaration, followed by a Java initialization:

int main()
{
    point_2d point;

    point = point_2d( 10.0f , 10.0f ); //WTF!!!
}

Depending on the compiler, or if the optimizations are turned off (Everybody knows that noobs never enable optimizations...), this result in:

  • A call to point_2d constructor (The explicit call)
  • A call to point_2d::operator=
  • A call to point_2d destructor (Destruction of the temporal created by the ctor call).

Or, finally, the same but everything in the same line:

int main()
{
    point_2d point = point_2d( 10.0f , 10.0f ); //WTF!!!
}

That is a call to the point_2d constructor followed by a call to the point_2d copy constructor to initialize the variable with the created temporal.

Note that performance in this case is not the point, because thats not the C++ stye/way to do things. Everybody who writes C++ code in that way, should go to buy a good C++ book. Effective C++ was redited with upcoming Java-like programmers in mind.