{"id":103874,"date":"2020-06-18T07:00:00","date_gmt":"2020-06-18T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103874"},"modified":"2020-06-19T06:39:47","modified_gmt":"2020-06-19T13:39:47","slug":"20200618-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200618-00\/?p=103874","title":{"rendered":"Understanding warning C4265: class has virtual functions, but destructor is not virtual, part 1"},"content":{"rendered":"<p>A few customers have noted that compiling WRL and C++\/WinRT headers generate warning C4265: class has virtual functions, but destructor is not virtual.<\/p>\n<p>What&#8217;s this warning trying to say?<\/p>\n<p>If a non-final class has a virtual method, then the compiler considers the possibility that there will be a derived class which overrides that virtual method. And if the class does not have a virtual destructor when a pointer to the base class is <code>delete<\/code>d, then only the destructor for the base class will run; the destructor for the derived class will not run.\u00b9<\/p>\n<pre>struct Base\r\n{\r\n  virtual void f();\r\n};\r\n\r\nstruct Derived : Base\r\n{\r\n ~Derived();\r\n};\r\n<\/pre>\n<p>In the above case, the warning is generated because of this possibility:<\/p>\n<pre>void Finish(Base *base)\r\n{\r\n delete base;\r\n}\r\n\r\nvoid Something()\r\n{\r\n  auto d = new Derived();\r\n  Finish(d);\r\n}\r\n<\/pre>\n<p>If a pointer points to a base class, but the pointer points at runtime to a derived class, then the base class must have a virtual destructor in order to destruct the derived class. Without the virtual destructor, only the destructor for the base class will run.<\/p>\n<p>However, if you never do a <code>delete base<\/code>, then the problem never arises.<\/p>\n<p>The compiler is warning about a potential trap, rather then waiting for you to fall into the trap. This means that if you are careful to avoid the trap, you have no actual problem, but the compiler will warn you about it anyway.\u00b2<\/p>\n<p>If you know that nobody derives from <code>Derived<\/code>, you can mark it as <code>final<\/code>, which will make the warning go away.<\/p>\n<p>Next time, we&#8217;ll apply this understanding to WRL and C++\/WinRT.<\/p>\n<p>\u00b9 Formally, the behavior is undefined. See <b>[expr.delete]<\/b> paragraph 3.<\/p>\n<blockquote class=\"q\"><p>If the static type of the object to be deleted is different from its dynamic type\u2026, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or <u>the behavior is undefined<\/u>.<\/p><\/blockquote>\n<p>\u00b2 I would prefer the compiler wait until you actually do the <code>delete<\/code> before generating the warning. But it&#8217;s being proactive and warning about a potential problem, even if that potential is not realized immediately.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What&#8217;s it trying to warn you about? Does it matter?<\/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-103874","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>What&#8217;s it trying to warn you about? Does it matter?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103874","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=103874"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103874\/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=103874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}