📜 ⬆️ ⬇️

C ++ MythBusters. The myth of the virtual functions (addition)

Preamble


Good evening (well, or to whom).

Not so long ago, I stumbled upon the article on virtual functions in C ++ (it is here now). I would be happy to add a comment, but as it turned out, you need to have a registration here. Actually, that's why I wrote this post-supplement to the above article.

In this article I want to touch on the issue of virtuality of constructors, destructors, as well as specific issues one way or another connected with the virtuality of functions.
')
The article is designed for programmers of medium and high qualification. Enjoy reading.

Virtual Constructors in C ++


So, let's start with the designers. It's all very simple - virtual constructors (as well as similar constructors) do not exist in C ++. Just because it does not happen and that's it (specifically: it is prohibited by the standard language).

You will probably ask: "But why is this even necessary?" In fact, the conversation about the “virtual constructor” is a bit incorrect. A constructor cannot be virtual in the sense of virtual functions, since so that there is a need for virtuality in the constructor (and there is no special place anymore) to set the pointer to the TVM (virtual functions table) for the object being created.

Note : usually virtuality is realized through TVM and a pointer to it in the object. Read more about this here.

So, sometimes the “virtual constructor” refers to the mechanism for creating an object of any previously unknown class. This can be useful, for example, when copying an array of objects inherited from a common ancestor (and we would very much like to call the copy constructor of the class we need, of course). In C ++, for a like, usually, a virtual function like virtual void assign (const object &o) , or similar is used, however, this is not ubiquitous, and other implementations are possible.

Virtual destructor


But the destructor, on the contrary, can be virtual. And even more than that - it is often found.
It is common to use a Wirth destructor in classes that have a Wirth function. Moreover, gcc, for example, will warn you if you do not make a virtual destructor by declaring a virtual function.

You can often find the myth: “A Wirth destructor is needed only if the non-standard functions are assigned to the destructor of the descendant classes, if the destructor of the descendant does not differ in functionality from the parent, then making it virtual does not make much sense”. It can and will work “now”, but it can play a cruel joke in the future, and in general is not very true. If the destructor is not virtual, then a destructor of the type specified in the pointer will be called. At the same time, it will be more correct that for the objects of descendants their destructors should be called. It’s just worth accepting as a rule, otherwise in the future there may be very big problems with debugging why it is not clear why programs are flowing in terms of memory.

Another myth: pure virtual destructors do not exist. More like they are.
class Sample {
public :
virtual ~Sample()=0;
};


* This source code was highlighted with Source Code Highlighter .

There is a myth that this class is abstract. And this is true.
It is also a common misconception that nalsdeniki of this class will be polymorphic. This is incorrect - destructors are not inherited.
There is a myth that a descendant of this class cannot be created. You can, here is an example:
class Sample {
public :
virtual ~Sample()=0{} // , , MS VC
};

class DSample: public Sample {

};


* This source code was highlighted with Source Code Highlighter .


For sane compilers, the Sample class needs to be written like this:
class Sample {
public :
virtual ~Sample()=0;
};

Sample::~Sample() {
}

* This source code was highlighted with Source Code Highlighter .

Immediately a remark about the normality of the compiler, and at the same time a myth: according to the standard, define purely Wirth. a function inside a class definition is impossible. But certain corporations say “if we see an opportunity to improve the standard, then we do it without thinking.”

Have you ever seen purely virtual destructors with certain “bodies”? So, the myth that they do not exist is also incorrect. You can also define other pure virtual functions.

Why do I need to write with the definition of a destructor? The answer is really simple: from the DSample in the destructor ~ DSample the ~ Sample destructor will be called, and therefore it must be defined, otherwise you will not even have to compile it.

Why do we need such a pure virtual destructor? This is used to make the class abstract without creating purely virtual functions. I could not find any other use.

Notes on device pointers to a member function


It would seem that this part is not related to virtuality. If you think so, you are greatly mistaken. Generally speaking, C ++ member function pointers are used less frequently. This is partly due to muddy (as it seems to me) chapters in the language standard, in part, because their implementation results in a complete nightmare for compiler programmers. I do not know of a single compiler that could work with these “pieces” completely according to the standard.

If you really want to know how it works inside (break brains at the same time), then I advise you to contact us at www.rsdn.ru/article/cpp/fastdelegate.xml , everything is described in great detail there. Just do not say that I did not warn you.

Conclusion


That's probably all that I would like to tell you in addition. Of course, some of the issues related to virtuality still require discoveries, leaving it to your conscience 8)

Good luck in programming.

PS it would be necessary to transfer the blog to the CPP ... I think there it will be more in demand.

Source: https://habr.com/ru/post/51398/


All Articles