{"id":833,"date":"2011-12-12T20:24:40","date_gmt":"2011-12-12T08:24:40","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=833"},"modified":"2011-12-12T20:28:22","modified_gmt":"2011-12-12T08:28:22","slug":"respect-your-ancestors","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/833\/","title":{"rendered":"Respect Your Ancestors"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>Yesterday I posted <a href=\"https:\/\/plus.google.com\/u\/0\/111874043401122099650\/posts\">an observation on Google+, lamenting the lack of a compiler warning when code in an overridden method failed to call any inherited implementation<\/a>.  This simple oversight in an <strong>AfterConstruction<\/strong> override in a situation where the observed bug that arose (a memory leak) could just as easily have been the consequence of a more complex error on my part, caused me to spend a significant amount of time, hunting down the <em>wrong bug<\/em>.<br \/>\n<!--more--><\/p>\n<p><a href=\"https:\/\/plus.google.com\/u\/0\/118329774029340938562\/posts\">Eric Grange<\/a> suggested that <strong>AfterConstruction<\/strong> and <strong>BeforeDestruction<\/strong> was best forgotten.  This was an interesting thought, but when I considered it I concluded that I had to disagree.  Not only would it not help me avoid my problem had I ignored them, but doing so would merely have created new opportunities to introduce such time-wasting bugs.<\/p>\n<p><strong>AfterConstruction<\/strong> and <strong>BeforeDestruction<\/strong> fulfil a genuine need imho.  Most especially I have found them of immense utility when creating frameworks.  In a framework I find I often have a base class (or classes) from which further classes are intended to be derived, with (potentially) overridden constructors.  Also quite often, the base class never-the-less requires some internal initialisation to reliably occur only after any overridden construction has been completed.<\/p>\n<p>In the specific case that led to my initial post, the base class in question contained an interface reference counting bug fix I originally developed long before it was fixed in the VCL.  Actually, it addresses a duo of bugs, one of which manifests during construction and the other during destruction.  From memory (my Windows VM is not currently running so I can&#8217;t check the VCL source to be certain), the VCL now addresses the constructor side of things but not the destructor.<\/p>\n<p>In any event, my base class incorporates a <strong>NewInstance<\/strong> override (effectively <em>BeforeConstruction<\/em>) and an accompanying <strong>AfterConstruction<\/strong> implementation that operated to ensure a positive reference count during the execution of those constructors.  This addresses the situation where an object references itself using an interface during construction (e.g. passing a reference to itself to some other object which then discards it) resulting in the reference count &#8220;bouncing&#8221;, falling back to zero and thus destroying itself.  A similar mechanism using <strong>BeforeDestruction<\/strong> ensures that &#8220;double-destruction&#8221; doesn&#8217;t occur if self is reference as an interface during <em>destructor<\/em> execution).<\/p>\n<p>If <strong>AfterConstruction<\/strong> and <strong>BeforeDestruction<\/strong> didn&#8217;t exist (or you ignored them) then in such circumstances you would simply have to contrive your own exactly <em>equivalent<\/em> mechanism.  This mechanism would still &#8211; by necessity &#8211; rely on <em>virtual<\/em> methods and <em>override<\/em>s and so as far as I can see will <em>still be vulnerable to the omission of calls to the inherited implementation<\/em>.<\/p>\n<p>But worse, without it being implemented in the base framework further steps would most likely be required to ensure that the alternate mechanism was correctly invoked.  As far as I can see, ignoring the provided core mechanism and &#8220;rolling your own&#8221;  would only compound the problem, increasing the potential to introduce a mistake rather than reducing it.<\/p>\n<p>Setting aside the rights or wrongs of an <strong>AfterConstruction<\/strong> or <strong>BeforeDestruction<\/strong> mechanism in the specific, in the general case overriding a method and then neglecting to call &#8220;inherited&#8221; is a sufficiently rare occurrence that it would be worth warning about imho.<\/p>\n<p>Furthermore, the compiler directive(s) required to then silence that warning would provide a self documenting and clear signal that the omission is indeed intentional, expected and indeed required (in those rare cases that it genuinely is).<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>Yesterday I posted an observation on Google+, lamenting the lack of a compiler warning when code in an overridden method failed to call any inherited implementation. This simple oversight in an AfterConstruction override in a situation where the observed bug that arose (a memory leak) could just as easily have been the consequence of a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[4,133],"tags":[],"class_list":["post-833","post","type-post","status-publish","format-standard","hentry","category-delphi","category-google"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-dr","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/833","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=833"}],"version-history":[{"count":4,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/833\/revisions"}],"predecessor-version":[{"id":837,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/833\/revisions\/837"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=833"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=833"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}