{"id":1349,"date":"2015-10-22T23:47:23","date_gmt":"2015-10-22T22:47:23","guid":{"rendered":"http:\/\/netrix.org.pl\/?p=1349"},"modified":"2015-10-23T15:41:55","modified_gmt":"2015-10-23T14:41:55","slug":"deleting-method-in-class-hierarchy","status":"publish","type":"post","link":"https:\/\/netrix.org.pl\/index.php\/2015\/10\/22\/deleting-method-in-class-hierarchy\/","title":{"rendered":"Deleting method in class hierarchy"},"content":{"rendered":"<p>C++11 has this new feature that allows programmer to remove:<\/p>\n<ul>\n<li>automatically generated method or operator,<\/li>\n<li>overload of free function or method (from implicit conversion)<\/li>\n<li>specialization of template method.<\/li>\n<\/ul>\n<p>This can be done by marking any function with <em>= delete<\/em> keyword and it works like this:<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nvoid foo(unsigned a)\r\n{}\r\nvoid foo(int) = delete;                         \/\/ deleted function overload for implicit conversion to int\r\n\r\ntemplate<class T>\r\nvoid bar(T a) \r\n{}\r\ntemplate<class T>\r\nvoid bar<double>(double) = delete;              \/\/ deleted template function specialization for double type\r\n\r\nstruct Foo \r\n{\r\n    Foo& operator=(Foo const&) = delete;        \/\/ deleted defaultly generated copying assignment operator\r\n\r\n    void call(unsigned a) {}\r\n    void call(int a) = delete;                  \/\/ deleted method overload for implicit conversion to int\r\n};\r\n\r\nint main()\r\n{\r\n    foo(1u);\r\n    \/\/foo(2);     \/\/ error: use of deleted function 'void foo(int)'\r\n\r\n    bar(Foo());\r\n    \/\/bar(4.0);   \/\/ error: use of deleted function 'void bar(T) [with T = double]'\r\n\r\n    Foo f;\r\n    f.call(1u);\r\n    \/\/f.call(2);  \/\/ error: use of deleted function 'virtual void Foo::call(int)'\r\n\r\n    Foo ff;\r\n    \/\/ff = f;     \/\/ error: use of deleted function 'Foo& Foo::operator=(const Foo&)'\r\n}\r\n<\/pre>\n<p>It is pretty simple and useful. This allows to remove not wanted specialization from any interface, e.g. overloaded signed value if unsigned and only unsigned value is required. Let consider following class hierarchy:<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n};\r\n<\/pre>\n<p>What if it is necessary to remove an overload of <em>call<\/em> method with <em>int<\/em> argument from interface of base class? Let see what will happen if different variants of <em>call<\/em> method are called from base class and derived class.<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    void call(unsigned a) {}\r\n    void call(int) = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    \/\/b.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>It works fine. <em>Bar<\/em> class uses <em>Foo<\/em> class method declaration so it is not possible to call the <em>call<\/em> method from both <em>Foo<\/em> and <em>Bar<\/em> classes. But what if a programmer would like to have the <em>call<\/em> method virtual and overridden in derived class?<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n    void call(int) = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n    void call(unsigned a) override {}\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    b.call(1);       \/\/ works since it's not deleted in derived class and can be implicitely casted to unsigned\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>Now it is possible to call the <em>call<\/em> method from <em>Bar<\/em> class but not from <em>Foo<\/em> class. But what if &#8216;virtual&#8217; is put before <em>void call(int) = delete<\/em>?<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n    virtual void call(int) = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n    void call(unsigned a) override {}\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    b.call(1);       \/\/ works since it's not deleted in derived class and can be implicitely casted to unsigned\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>It seems it does not matter if function is virtual or not. But there is another keyword that works with inheritence &#8211; <em>final<\/em> which means that virtual method marked with this keyword cannot be overriden in derived class.<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n    virtual void call(int) final = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n    void call(unsigned a) override {}\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    b.call(1);       \/\/ works since it's not deleted in derived class and can be implicitely casted to unsigned\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>It does not matter either if method is final or not. So one and only option is just to declare the <em>call<\/em> method with <em>int<\/em> argument as deleted in derived class which should be a first choice of those considerations.<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n    virtual void call(int) final = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n    void call(unsigned a) override {}\r\n    \/\/void call(int) = delete;           \/\/ error: use of deleted function 'virtual void Bar::call(int)'\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    b.call(1);       \/\/ works since it's not deleted in derived class and can be implicitely casted to unsigned\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>Ooops. Method <em>void call(int)<\/em> is marked as final in base class so it is not even possible to declare it as deleted in derived class. The one and only valid example that works as it supposed to from the beginning look like this:<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct Foo \r\n{\r\n    virtual void call(unsigned a) {}\r\n    void call(int) = delete;\r\n};\r\n\r\nstruct Bar : Foo\r\n{\r\n    void call(unsigned a) override {}    \/\/ If we want to override call()\r\n    using Foo::call;                     \/\/ if we want to use Foo::call()\r\n    void call(int) = delete;\r\n};\r\n\r\nint main()\r\n{\r\n    Bar b;\r\n    b.call(1u);\r\n    \/\/b.call(1);     \/\/ error: use of deleted function 'void Bar::call(int)'\r\n    Foo & f = b;\r\n    f.call(1u);\r\n    \/\/f.call(1);     \/\/ error: use of deleted function 'void Foo::call(int)'\r\n}\r\n<\/pre>\n<p>In conclusion it is not possible to declare the method overload as deleted in base class so that it will affect derived class if base method is marked as virtual and overriden in derived class. This concerns mostly the interfaces with methods that may accept some unsigned key value while there exists some signed key type, that should not be passed to considered methods.<\/p>\n<p>&#8212;<br \/>\nAll examples were compiled with GCC 5.2 with <em>&#8211;std=c++14<\/em> flag.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C++11 has this new feature that allows programmer to remove: automatically generated method or operator, overload of free function or method (from implicit conversion) specialization of template method. This can be done by marking any function with = delete keyword and it works like this: void foo(unsigned a) {} void foo(int) = delete; \/\/ deleted [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[187,188,189,190],"_links":{"self":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/1349"}],"collection":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1349"}],"version-history":[{"count":44,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/1349\/revisions"}],"predecessor-version":[{"id":1393,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/1349\/revisions\/1393"}],"wp:attachment":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}