Compiler Error C2694:
Error Description:
Overriding virtual function has less restrictive exception specification than base class virtual member funcion base.
Error Details:
Derived class is overriding some virtual function of the base class with lesser exception specification.
Error Concept:
Whenever any virtual function is declared with other properties related to the exceptions then it is expected that the Derived class implementing the base class virtual function should specify same exception as that of the Base class virtual function.
Compiler Flag:
/Za: If this flag is enable then it would allow the Microsoft specific extensions of the ISO C89/C90 which are not compatible with ISO standards. It means enabling such type of flag will actually won’t give compiler error because the code is fine as per the extended standards of microsoft. The risk is that the same code will give compiler error else-where because the style of coding is not compatible with ISO C89/C90.
Error Situations:
Let us have base class Base with as below.
class Base {
public:
virtual void f(void) throw(int) {
// this type of function definition is telling the compiler that this function could throw error of type integer.
}
};
class Derived : public Base {
public:
void f(void) throw(...){}
// here in ths definition the throw is not specifying the exception type. Thus compiler will emit error here.
// void f(void) throw(int){} This definition is correct way to define in base class
};
Since C++11 standards the exception declaration in function is given by noexcept as below:
class Base {
protected:
virtual void display(void) noexcept;
};
class Derived:public Base {
void display(void) noexcept {// some definition}
};
Addition Information:
noexcept :The noexcept specification is not a part of function type. It can only appear as lambda declarator or top level function declaration when declaring functions. This could also appear as part of declaration for variables, non-static data members which are of type function, pointer to function or reference to function or pointer to member function. This may also appear as argument to function of type function.
void f() noexcept; // function f doesn't throw any exceptions
void (*fp)() noexcept(false);
// fp a pointer to function with no arguments is actually specifying that
//the function pointed by this function pointer can throw exception.
Additional Rules:
-
Function definiton differing only in their exception specification can’t be overloaded. That is we can’t have function with same signature but with one specifying the exception and another saying no exception.
-
Any function which donot have noexcept means it can potentially throw exception. Thus it is equivalent to noexcept(false) but not noexcept.
-
If base class function declaration is not using noexcept then it actually means it may throw exception. But declaration wise it indicates as if it is non throwing. Thus in Derived class while specifyin the declaration of overriding such function one can declare noexcept with non throwing only.
-
If base class function declaration is using noexcept then Derived class can’t remove noexcept it has to have noexcept with same level of exception specification as that of the Base class.
-
If Base class virtual function with non-throwing is declare to be deleted then in Derived class the noexcept could be dropped.
-
If outer function is non-throwing and it is calling a function which could potentially throw then std::terminate of std::unexpected is called. Note this gets change with C++17 and prior to that
-
noexcept prior to C++17 doesn’t gaurantess about stack unwinding or may not call std::unexpected. Thus is allows compiler to implement noexcept wihtout runtime overhead of throw(). But in C++17 throw() is equivalent to noexcept(true)
Comments
Join the discussion for this article on this ticket. Comments appear on this page instantly.