Why do we need virtual functions in C++?

前端 未结 26 3176
北恋
北恋 2020-11-21 05:50

I\'m learning C++ and I\'m just getting into virtual functions.

From what I\'ve read (in the book and online), virtual functions are functions in the base class that

26条回答
  •  灰色年华
    2020-11-21 06:09

    OOP Answer: Subtype Polymorphism

    In C++, virtual methods are needed to realise polymorphism, more precisely subtyping or subtype polymorphism if you apply the definition from wikipedia.

    Wikipedia, Subtyping, 2019-01-09: In programming language theory, subtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability, meaning that program elements, typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype.

    NOTE: Subtype means base class, and subtyp means inherited class.

    Further reading regarding Subtype Polymorphism

    • https://en.wikipedia.org/wiki/Subtyping
    • https://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping

    Technical Answer: Dynamic Dispatch

    If you have a pointer to a base class, then the call of the method (that is declared as virtual) will be dispatched to the method of the actual class of the created object. This is how Subtype Polymorphism is realised is C++.

    Further reading Polymorphism in C++ and Dynamic Dispatch

    • http://www.cplusplus.com/doc/tutorial/polymorphism/
    • https://en.cppreference.com/w/cpp/language/virtual

    Implementation Answer: Creates vtable entry

    For each modifier "virtual" on methods, C++ compilers usually create an entry in the vtable of the class in which the method is declared. This is how common C++ compiler realise Dynamic Dispatch.

    Further reading vtables

    • https://en.wikipedia.org/wiki/Virtual_method_table

    Example Code

    #include 
    
    using namespace std;
    
    class Animal {
    public:
        virtual void MakeTypicalNoise() = 0; // no implementation needed, for abstract classes
        virtual ~Animal(){};
    };
    
    class Cat : public Animal {
    public:
        virtual void MakeTypicalNoise()
        {
            cout << "Meow!" << endl;
        }
    };
    
    class Dog : public Animal {
    public:
        virtual void MakeTypicalNoise() { // needs to be virtual, if subtype polymorphism is also needed for Dogs
            cout << "Woof!" << endl;
        }
    };
    
    class Doberman : public Dog {
    public:
        virtual void MakeTypicalNoise() {
            cout << "Woo, woo, woow!";
            cout << " ... ";
            Dog::MakeTypicalNoise();
        }
    };
    
    int main() {
    
        Animal* apObject[] = { new Cat(), new Dog(), new Doberman() };
    
        const   int cnAnimals = sizeof(apObject)/sizeof(Animal*);
        for ( int i = 0; i < cnAnimals; i++ ) {
            apObject[i]->MakeTypicalNoise();
        }
        for ( int i = 0; i < cnAnimals; i++ ) {
            delete apObject[i];
        }
        return 0;
    }
    

    Output of Example Code

    Meow!
    Woof!
    Woo, woo, woow! ... Woof!
    

    UML class diagram of code example

提交回复
热议问题