To be virtual or not to be virtual

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • To be virtual or not to be virtual

      Hello there,
      I have recently bought the GCC book. It's great and I am really enjoying it :). Anyways, let me ask my question.

      Source Code

      1. class A{
      2. public:
      3. virtual void VDraw(){ std::cout << "A" << std::endl; }
      4. };
      5. class B: public A{
      6. public:
      7. B(){}
      8. void VDraw(){ std::cout << "B" << std::endl; } // Do we need a "virtual" specifier here? Does it make any difference?
      9. };
      10. class C: public B{
      11. public:
      12. C(){}
      13. void VDraw(){ std::cout << "C" << std::endl; } // Do we need a "virtual" specifier here? Does it make any difference?
      14. };
      Display All

      As you can see from the comments in the code section, I am wondering whether virtual keyword makes any difference if it is typed in the derived class. I am also confused with the "override" keyword used in the page 65 of the book. As far as I know; if the signature of the method in the derived class is exactly the same, it is already overriding the "base method". So, what is the deal with this "override" keyword?

      Thanks :).
    • RE: To be virtual or not to be virtual

      Originally posted by column_vector
      As you can see from the comments in the code section, I am wondering whether virtual keyword makes any difference if it is typed in the derived class.

      Technically, you only need the virtual keyword on the top-level function. The virtualness of the function is inherited. However, the convention is to always use the virtual keyword all the way down the inheritance tree. It improves readability by making your intentions more explicit. Similarly, you can have a variable defined like this:

      Source Code

      1. unsigned x;


      Which is exactly the same as this:

      Source Code

      1. unsigned int x;


      The latter is used over the former because it improves readability. Remember, you're not writing code for the computer, you're writing code for other programmers (or for yourself 3 months down the line). You should be as explicit as possible.

      As another example, say I have the following code:

      Source Code

      1. B* pObj = new C;
      2. pObj->VDraw();


      This will work just fine. Now, say I get rid of the base-class version of VDraw(). When I call VDraw() on pObj, I will no longer be calling the C version, I'll be calling the B version because it's no longer virtual. I would have to remember to go in to each class that inherits directly from A and add the virtual keyword. A small change just became a bigger change, and one that possibly introduces bugs into the code.


      I am also confused with the "override" keyword used in the page 65 of the book. As far as I know; if the signature of the method in the derived class is exactly the same, it is already overriding the "base method". So, what is the deal with this "override" keyword?

      The override keyword marks the function as explicitly being an override. If you remove the base-class function or rename it, it will throw a compiler error if you don't also rename the subclass functions. This is a common source of bugs. For example, say I have the following definition:

      Source Code

      1. class Base
      2. {
      3. public:
      4. virtual void Draw(void)
      5. {
      6. // do render stuff here
      7. }
      8. };
      9. class SubClass : public Base
      10. {
      11. public:
      12. virtual void Draw(void)
      13. {
      14. // Do different render stuff here
      15. }
      16. };
      Display All


      Now let's say that I rename Draw() to Render() in the base class but forget to do it in the sub class. When I call Render() on SubClass, it'll call the base class version when I meant to call the sub class version. If I had used the override keyword on SubClass::Draw(), I would have gotten a compilation error.

      One disadvantage of the override keyword is that it's not entirely portable. It's been a Visual Studio thing for a while and is only just now being introduced into C++ as an official keyword. Another related keyword is final, which visual studio doesn't support yet (though it does support sealed, which has the exact same effect). When applying this to a virtual function, it will no longer allow subclasses to override it. This can be very handy for interfaces where you don't want certain methods to be overridden. In GCC (and my own projects), I have a macro that just replaces final with sealed:

      Source Code

      1. #define final sealed


      Hopefully, VS will add support for the rest of the new C++ standard soon.

      -Rez
    • Yeah, it's not a big deal when you only have a few thousand lines of code, but most games have hundreds of thousands or more. The Sims Medieval was well over a million. My own simple 2D game engine has about 35,000 lines, and that's just the engine with no genre or game layer.

      -Rez
    • Yup, that's what I meant when I said that override and final are just making it into the C++ standard. They are official as of C++ 11, though Visual Studio 2010 doesn't quite support them. Hopefully they'll add support in a service pack.

      -Rez