{"id":39613,"date":"2004-04-28T07:00:00","date_gmt":"2004-04-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/04\/28\/what-is-__purecall\/"},"modified":"2004-04-28T07:00:00","modified_gmt":"2004-04-28T07:00:00","slug":"what-is-__purecall","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040428-00\/?p=39613","title":{"rendered":"What is __purecall?"},"content":{"rendered":"<p>\nBoth C++ and C# have the concept of virtual functions.\nThese are functions which always invoke the most heavily\nderived implementation, even if called from a pointer to\nthe base class.\nHowever, the two languages differ on the semantics of\nvirtual functions during object construction and destruction.\n<\/p>\n<p>\nC# objects exist as their final type before construction begins,\nwhereas C++ objects change type during the construction process.\n<\/p>\n<p>\nHere&#8217;s an example:\n<\/p>\n<pre>\nclass Base {\npublic:\n  Base() { f(); }\n  virtual void f() { cout &lt;&lt; 1; }\n  void g() { f(); }\n};\nclass Derived : public Base {\npublic:\n  Derived() { f(); }\n  virtual void f() { cout &lt;&lt; 2; }\n};\n<\/pre>\n<p>\nWhen a <code>Derived<\/code> object is constructed,\nthe object starts as a <code>Base<\/code>, then the\n<code>Base::Base<\/code> constructor is executed.\nSince the object is still a <code>Base<\/code>,\nthe call to <code>f()<\/code> invokes <code>Base::f<\/code>\nand not <code>Derived::f<\/code>.\nAfter the <code>Base::Base<\/code> constructor completes,\nthe object then becomes a <code>Derived<\/code> and\nthe <code>Derived::Derived<\/code> constructor is run.\nThis time, the call to <code>f()<\/code> invokes\n<code>Derived::f<\/code>.\n<\/p>\n<p>\nIn other words, constructing a <code>Derived<\/code>\nobject prints &#8220;12&#8221;.\n<\/p>\n<p>\nSimilar remarks apply to the destructor.\nThe object is destructed in pieces, and a call to\na virtual function invokes the function corresponding\nto the stage of destruction currently in progress.\n<\/p>\n<p>\n<strong>This is why some coding guidelines recommend against\ncalling virtual functions from a constructor or destructor<\/strong>.\nDepending on what stage of construction\/destruction is taking place,\nthe same call to <code>f()<\/code> can have different effects.\nFor example, the function <code>Base::g()<\/code> above\nwill call <code>Base::f<\/code>\nif called from the <code>Base::Base<\/code>\nconstructor or destructor,\nbut will call <code>Derived::f<\/code>\nif called after the object has been constructed and before\nit is destructed.\n<\/p>\n<p>\nOn the other hand, if this sample were written\n(with suitable syntactic changes) in C#,\nthe output would be &#8220;22&#8221;\nbecause a C# object is created as its final type.\nBoth calls to <code>f()<\/code> invoke <code>Derived::f<\/code>,\nsince the object is always a <code>Derived<\/code>.\nNotice that means <strong>a method can be invoked on an object\nbefore its constructor has run<\/strong>.\nSomething to bear in mind.\n<\/p>\n<p>\nSometimes your C++ program may crash with the error\n&#8220;R6025 &#8211; pure virtual function call&#8221;.\nThis message comes from a function called __purecall.\nWhat does it mean?\n<\/p>\n<p>\nC++ and C# both have the concept of a &#8220;pure virtual function&#8221;\n(which C# calls &#8220;abstract&#8221;).\nThis is a method which is declared by the base class,\nbut for which no implementation is provided.\nIn C++ the syntax for this is &#8220;=0&#8221;:\n<\/p>\n<pre>\nclass Base {\npublic:\n  Base() { f(); }\n  virtual void f() <font COLOR=\"blue\">= 0<\/font>;\n};\n<\/pre>\n<p>\nIf you attempt to create a <code>Derived<\/code> object,\nthe base class will attempt to call <code>Base::f<\/code>,\nwhich does not exist since it is a pure virtual function.\nWhen this happens, the &#8220;pure virtual function call&#8221; error\nis raised and the program is terminated.\n<\/p>\n<p>\nOf course, the mistake is rarely as obvious as this.\nTypically, the call to the pure virtual function occurs\ndeep inside the call stack of the constructor.\n<\/p>\n<p>\nThis raises the side issue of\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/vclang\/html\/_langref_novtable.asp\">\nthe &#8220;novtable&#8221; optimization<\/a>.\nAs we noted above, the identity of the object changes\nduring construction.  This change of identity is performed\nby swapping the vtables around during construction.\nIf you have a base class that is never instantiated\ndirectly but always via a derived class, and\n<strong>if you have followed the rules against calling\nvirtual methods during construction<\/strong>,\nthen you can use the novtable optimization to get rid of\nthe vtable swapping during construction of the base class.\n<\/p>\n<p>\nIf you use this optimization, then\n<strong>calling virtual methods during the base class&#8217;s\nconstructor or destructor will result in undefined behavior<\/strong>.\nIt&#8217;s a nice optimization, but it&#8217;s your own responsibility to make\nsure you conform to its requirements.\n<\/p>\n<p>\n<b>Sidebar<\/b>: Why does C# not do type morphing during construction?\nOne reason is that it would result in the possibility,\ngiven two objects A and B, that\ntypeof(A) == typeof(B) yet sizeof(A) != sizeof(B).\nThis would happen if A were a fully constructed object and B\nwere a partially-constructed object on its way to becoming\na derived object.\n<\/p>\n<p>\nWhy is this so bad?  Because the garbage collector is really keen\non knowing the size of each object so it can know how much memory\nto free.  It does this by checking the object&#8217;s type.\nIf an object&#8217;s type did not completely determine its size,\nthis would result in the garbage collector having to do extra\nwork to figure out exactly how big the object is,\nwhich means extra code in the constructor and destructor,\nas well as space in the object,\nto keep track of which stage of construction\/destruction is\ncurrently in progress.  And all this for something most coding\nguidelines recommend against anyway.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Both C++ and C# have the concept of virtual functions. These are functions which always invoke the most heavily derived implementation, even if called from a pointer to the base class. However, the two languages differ on the semantics of virtual functions during object construction and destruction. C# objects exist as their final type before [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-39613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Both C++ and C# have the concept of virtual functions. These are functions which always invoke the most heavily derived implementation, even if called from a pointer to the base class. However, the two languages differ on the semantics of virtual functions during object construction and destruction. C# objects exist as their final type before [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/39613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=39613"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/39613\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=39613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=39613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=39613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}