C++: Why does a struct\class need a virtual method in order to be polymorphic?

∥☆過路亽.° 提交于 2019-12-09 02:28:08

问题


Following this question, I'm wondering why a struct\class in C++ has to have a virtual method in order to be polymorphic.

Forcing a virtual destructor makes sense, but if there's no destructor at all, why is it mandatory to have a virtual method?


回答1:


Because the type of a polymorphic object in C++ is, basically, determined from the pointer to its vtable, which is the table of virtual functions. The vtable is, however, only created if there's at least one virtual method. Why? Because in C++, you never get what you didn't explicitly ask for. They call it "you don't have to pay for something you don't need". Don't need polymorphism? You just saved a vtable.




回答2:


Forcing a virtual destructor makes sense

Exactly. To destruct a virtual class manually (via delete) through its base class you need a virtual destructor. (Now, as I’ve been reminded in the comments, this isn’t usually needed: rather than use manual memory management, one would rely on modern smart pointers which also work correctly with non-virtual destructors.)

So any class which acts as a polymorphic base class usually needs either a virtual destructor or virtual functions anyway.

And since having runtime polymorphism adds an overhead (the class needs to store an additional pointer to its virtual method table), the default is not to add it, unless necessary anyway: C++’ design philosophy is “you only pay for what you need”. Making every class have a virtual method table would run afoul of this principle.




回答3:


Because it is defined as such in the standard.

From 10.3/1 [class.virtual]

Virtual functions support dynamic binding and object-oriented programming. A class that declares or inherits a virtual function is called a polymorphic class.

It makes sense that if you use inheritance, then you have at least one virtual method. If you don't have any virtual method, then you could use composition instead.




回答4:


polymorphism is to allow your subclasses to override the default behaviour of base class functions, so unless you have virtual methods in your base class, you can't override methods in base.




回答5:


I'm wondering why does a struct\class in C++ has to have a virtual method in order to be polymorphic?

Because that is what polymorphic class means.

In C++, runtime polymorphism is achieved through virtual functions. A base class declares some virtual functions which the many derived classes implement, and the clients use pointers (or references) of static type of base class, and can make them point to objects of derived classes (often different derived classes), and then later on, call the implementation of derived classes through the base pointers. That is how runtime polymorphism is achieved. And since the central role is played by the functions being virtual, which enables runtime polymorphism, that is why classes having virtual functions is called polymorphic class.




回答6:


Without any virtual method, there is no need to maintain a virtual pointer (abbreviated as vptr) for every object of the class. The virtual pointer is a mechanism for resolving virtual method calls at runtime; depending on the object's class, it might point to different virtual method tables (abbreviated as vtable) that contain the actual adresses of virtual methods.

So by checking to what vtable does the vptr point to, compiler can determine object's class, for example in dynamic_cast. Object without the vptr cannot have its type determined this way and is not polymorphic.




回答7:


A C++ design philosophy is that "you don't pay for what you don't use". You might already know that a virtual function incur some overhead as a class has to maintain a pointer to its implementation. In fact, an object contains a reference to a table of function pointers called the vtable.

Consider the following example:

class Base
{
public:
    virtual f() { /* do something */ }
}; 

class Derived : public Base
{
public:
    virtual f() { /* do something */ }
}; 

Base* a = new Derived;
a->f(); // calls Derived::f()

Note that the variable a points to a Derived object. As f() is declared virtual the vtable of a will contain a pointer to Derived::f() and that implementation is executed. If f() is not virtual, the vtable will be empty. So Base::f() is executed as the type of a is Base.

A destructor behaves just like other member functions. If the destructor is not virtual, only the destructor in the Base class will be called. This might lead to memory/resource leaks if the Derived class implements RAII. If a class is intended to be sub-classed, its destructor should be virtual.

In some languages like Java all methods are virtual. So even objects that are not intended to be polymorphic will consume memory for maintaining the function pointers. In other words, you are forced to pay for what you don't use.




回答8:


Classes only need virtual methods in order to be dynamically polymorphic - for the reasons described by others. You can still have static polymorphism through templates, though.



来源:https://stackoverflow.com/questions/5831863/c-why-does-a-struct-class-need-a-virtual-method-in-order-to-be-polymorphic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!