C++ - Virtual functions & Abstract class

Created:2018-01-19  Last modified:2019-03-19


  1. Virtual Functions

    Virtual function (A special override) achieved a runtime polymorphism instead of compile-time. [late binding]

    It allowes a child class object but is declared as parent class to call the child functions.

    Only accessing via pointer or reference of parent type can achieve the runtime polymorphism.

    for deconstructor

    Features

    1. Only parent class need the virtual keyword
    2. No virtual member variables
    3. Private/Protected modifier is static, but virtual function is dynamic.
    4. virtual functions can be defined as public, protected or private in the Parent class. But Attention: modifier is static even with a pointer or reference type

    Examples

    1. Basic

              #include <iostream>
              using namespace std;
      
              class Parent{
              public:
                  Parent() {
                      cout << "Parent constructor" << endl;
                  }
                  void display() {
                      cout << "Parent display" << endl;
                  }
                  virtual void virtualDisplay() {
                      cout << "Parent virtual display "  << endl;
                  }
              };
              
              class Child: public Parent{
              public:
                  Child() {
                      cout << "Child Constructor" << endl;
                  }
                  void display() {
                      cout << "Child display" << endl;
                  }
                  void virtualDisplay() {
                      cout << "Child virtual display "  << endl;
                  }
              };
      
              void callByReference(Parent & p){
                  p.virtualDisplay();
              }
              void callByValue(Parent p){
                  p.virtualDisplay();
              }
              int main(){
                  Child c; // "Parent constructor /n Child constructor"
                  Parent p2 = c; /* it is just an assignment, but p2 is staticly bind to c's inherited parent method*/
                  Parent * p = &c;
                  p->display(); // Parent display
                  p->virtualDisplay(); // Child virtual display
                  p2.virtualDisplay(); // Parent virtual display
                  
                  callByReference(c); //Child virtual display
                  callByValue(c); //Parent virtual display
                  return 0;
              }
      
    2. Protected virtual function: provide an encapsulation

              #include <iostream>
              using namespace std;
              class Parent{
              public:
                  Parent();
                  void display();
              protected:
                  virtual void virtualDisplay();
              };
              Parent::Parent(){
                  cout << "Parent constructor" << endl;
              }
              void Parent::display(){
                  // do something
                  virtualDisplay();
                  // do something
              }
              void Parent::virtualDisplay(){
                  cout << "Parent virutal display" << endl;
              }
              //========
              class Child: public Parent{
              public:
                  Child();
              protected:
                  void virtualDisplay();
              };
              Child::Child(){
                  cout << "Child Constructor" << endl;
              }
              
              void Child::virtualDisplay(){
                  cout << "Child virtual display "  << endl;
              }
              void callByReference(Parent & p){
                  p.display();
              }
              void callByValue(Parent p){
                  p.display();
              }
              int main(){
                  Child c; // Parent constructor /n Child constructor
                  Parent p2 = c;
                  Parent * p = &c;
                  p->display(); // Child virtual display
                  callByReference(c); //Child virtual display
                  callByValue(c); //Parent virtual display
                  return 0;
              }
      
    3. Static binded modifier

      Source code

      #include <iostream>
      using namespace std;
      class F{
      private:
          virtual void func(){cout << "Parent Private virtual function" << endl;}
      
      };
      class E: public F{
      public:
          void func(){cout << "Child Public virtual function" << endl;}
      
      };
      int main(){
          E e;
          F * f = &e;
          e.func();
          //f->func(); private modifer static bind
      }
      
  2. Abstract Class (Interface)

    Abstract class in C++ is similar to Java but without using abstract keyword. In C++, abstract class is achieved throught the virtual function. (C++ does not have interface)

        virtual void abstractFunction() = 0; // pure virtual function
    

    Pure virtual function

    In the parent declaration, we add a "= 0" after the virtual function, then the virtual function becomes a pure virtual function

    Pure virtual function is like java's abstract function, where we don't need to implement the function inside the parent class, and the parent class is not instantiatable. Subclass may implement this function if they want to be instantiated.

    class Parent{
        public:
            virtual void func() = 0;
            virtual void func2() const = 0; // virtual function cannot modify the value of this object
    }
    class Child{
        public:
            void func() override; // keyword comes from -suggest-override
            void func2() const override;
    }
    // In the .cc file, the "override" is not required, but const is still needed.
    // override is a mark, const is part of the signature.
    

    Abstract class features

    1. An abstract class: a class has at least one pure virtual function
    2. It is a compilation error to create an object of an abtract class.
    3. The drived class must implement parent pure virtual function, otherwise it is still an abstract class. Even if the virtual function is defined as a private function and it is not visible to the child class, the child class also has to implement it.