Question

Currently in my project I am making a virtual abstract base class and three derived class. In the base class's pure virtual function is used in the derived classes to create an equation that will either add or subtract with two variables. My problem is that I also have to include a function to check if one of the variables put into the function is negative that will throw an exception if it is. Currently I put these functions and the exceptions into the derived classes but to me it seems a little redundant. So I am wondering if it is allowed to put the function to check to see if the variable I'm checking is negative and have the exception thrown both in the abstract base class?

Was it helpful?

Solution 3

Yes, you can do that.

In the base class, you'll want to have two groups of functions:

  • Public, non-virtual functions that users of the class will call.
  • Protected, pure-virtual functions that will be implemented by the derived classes.

In the base class's public non-virtual functions, you can do any necessary argument checking, e.g. making sure that the argument isn't negative. Throw exceptions as necessary. Then, if the argument checks pass, call the corresponding virtual function to let the derived class do the rest.


Also, note that if negative numbers don't make sense for your function's arguments, it may be simper to just use unsigned types for those arguments.

OTHER TIPS

Just use the usual programming by contract pattern: make the pure virtual functions private, and provide a non-virtual function to check pre- and post-conditions and call the virtual. Something like:

class C
{
    virtual double doCalculate( double n ) = 0;
public:
    double calculate( double n ) {
        if ( n < 0.0 )
            throw whatever();
        return doCalculate( n );
    }
};

Yes, abstract class can throw exceptions from its functions. You should bare in mind however that

n3337 § 15.4/5:

If a virtual function has an exception-specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception-specification of the base class virtual function. [ Example:

struct B {
  virtual void f() throw (int, double);
  virtual void g();
};
struct D: B {
  void f();
  void g() throw (int);
};

The declaration of D::f is ill-formed because it allows all exceptions, whereas B::f allows only int and double. — end example ] A similar restriction applies to assignment to and initialization of pointers to functions, pointers to member functions, and references to functions: the target entity shall allow at least the exceptions allowed by the source value in the assignment or initialization. [ Example:

class A { /∗ ... ∗/ };
void (*pf1)();  // no exception specification
void (*pf2)() throw(A);

void f() {
  pf1 = pf2;  // OK: pf1 is less restrictive
  pf2 = pf1;  // error: pf2 is more restrictive
}

— end example ]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top