Browse DevX
Sign up for e-mail newsletters from DevX


Overriding Virtual Functions? Use C++0x Attributes to Avoid Bugs. : Page 3

Overriding a virtual member function in C++ can go wrong in many ways, most of which the compiler won't detect. Learn how three new C++0x attributes can help you avoid the bugs associated with overriding virtual functions.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Using Attributes

The compiler can't guess the programmer's intent. That is why misspelled function names and accidental hiding of base class functions go undetected. Three new C++0x attributes tackle this problem:
  • [[base_check]]: You use this attribute in a declaration of a derived class. It indicates that any name hiding or virtual function overriding within that class shall be marked with the appropriate attribute. Otherwise, a compilation error will occur.
  • [[override]]: This attribute applies to an overriding member function in a derived class. It indicates that a member function overrides a virtual function in a base class. If no appropriate virtual function is found, the program is ill formed.
  • [[hiding]]: This attribute indicates a member of a derived class that deliberately hides a member with the same name in a base class.

To "activate" the attributes [[override]] and [[hiding]], you first need to declare a derived class with the [[base_check]] attribute. Without [[base_check]], a derived class behaves as usual, allowing you to hide and override base class functions implicitly. A modified version of Derived looks like this:

struct Derived [[base_check]]: Base { void sone_func1 [[override]](); //error, spelling void some_func2 [[override]](); //error, signature void some_func3 [[override]](long long); //ditto };

Because the members of Derived are all declared [[override]], the compiler tries to match each one of them with a corresponding virtual function in the base class but fails. That leads to explicit compilation errors that tell the programmer exactly what's wrong with the code.

Hide and Seek

You can add new functions to a derived class as well. A new function is indicated by the lack of any attributes:

struct Derived [[base_check]]: Base { int new_func(); //OK //... };

In some cases, hiding a name in a derived class makes sense. For that purpose, you have to use the [[hiding]] attribute:

struct Derived [[base_check]]: Base { void some_func1[[hiding]](double);//OK void some_func2(short); //error, implicit hiding //... };

Implicit hiding in the class Derived isn't allowed, because that class is declared [[base_check]]. Omitting [[base_check]] will switch off the compiler's safeguards, reversing the validity of the functions' declarations:

struct Derived : Base { void some_func1[[hiding]](double);//error,[[base_check]] required void some_func2(short); //OK, implicit hiding //... };

Attributes Are Your Friends

The attributes proposal drew criticism because some believed it was conceived as a mechanism for sneaking keywords into C++ and because many people don't like the [[]] syntax. However, attributes are here to stay. They seem to solve a few annoying problems that previously had proved resistant to compilers.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Thanks for your registration, follow us on our social networks to keep up-to-date