Sunday, February 14, 2010

Table Class – Compilation

As mentioned, the Table constructor will throw an exception if any errors are found in the table. The caller of the Table constructor will look something like:

    Table *table;
    try
    {
        table = new table();
    }
    catch (List<TableError> *error_list)
    {
        ...output errors in error_list...
        exit(1);
    }

A test program was written to see if the basic concept of having a constructor throw and an error and then catching the error in the main routine. The test program test_cons will be in the next release. This worked as intended. However, as mentioned in the previous post, upon compiling table.cpp, the error list allocation line generated a compiler error essentially saying that constructor TableError::TableError() was missing. It was unknown where an empty constructor was being called since it wasn't being explicitly called. Guessing that it was missing a copy constructor for some reason, but adding one did not eliminate the error.

Now for a C++ Lesson: The source of the error was caused by the List class append() function. This function contains the line:

    Element *element = new Element;

This calls the constructor for Element with no arguments. The List<T>::Element structure does not contain any constructor (or any member functions), however it will look for a constructor (with no arguments) for each data member. Element contains two pointers (which would have no constructor) and T value. For simply types, there would be no constructor, however, in this case since T is TableError, it was looking for a constructor with no arguments, hence the compiler error. C++ would have automatically created a constructor (a constructor for each member of TableError, and in the case of TableError none would have been necessary since it only contains simple types), but only if there were no other constructors, which was not the case (two constructors were defined, so there is no automatic constructor).

A default constructor was added that sets the type to an unset error value (also added an unset enumeration value to the TableErrType enumeration). Problem solved. And it turns out that an empty constructor is needed in the catch code anyway to retrieve the errors from the error list as in:

    TableError error;                   <-- calls empty constructor
    while (error_list->remove(NULL, &error))
    {
        ...output error...
    }

One last thing to note in the code above, the remove() function of the List class was extended to remove the first item in the list if the element pointer argument is NULL (as used above). This saves having to get and pass in the pointer to the first element in the list (note that the remove() function with just the value pointer argument is for removing the last item in the list, as in used for popping the top item off a stack).

No comments:

Post a Comment

All comments and feedback welcomed, whether positive or negative.
(Anonymous comments are allowed, but comments with URL links or unrelated comments will be removed.)