{"id":842,"date":"2022-08-30T15:08:05","date_gmt":"2022-08-30T15:08:05","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors-in-vc-eclipse-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:08:05","modified_gmt":"2022-08-30T15:08:05","slug":"diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors-in-vc-eclipse-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors-in-vc-eclipse-collection-of-common-programming-errors\/","title":{"rendered":"Diamond-inheritance scenario compiles fine in G++, but produces warnings\/errors in VC++\/Eclipse-Collection of common programming errors"},"content":{"rendered":"<p>I have a base class &#8216;Base&#8217;, which is a pure virtual class:<\/p>\n<pre><code>class Base {\n\npublic:\n    virtual void A() = 0;\n    virtual void B() = 0;\n\n    virtual ~Base() { } \/\/ Eclipse complains that a class with virtual members must have virtual destructor\n};\n<\/code><\/pre>\n<p>I also have 2 other classes, one of them implements A() and the other one implements B():<\/p>\n<pre><code>class DerivedA : public virtual Base\n{\npublic:\n    virtual void A() {\n        printf(\"Hello from A\");\n    }\n};\n\nclass DerivedB : public virtual Base\n{\npublic:\n    virtual void B() {\n        printf(\"Hello from B\");\n    }\n};\n<\/code><\/pre>\n<p>The virtual keyword in the declaration should solve the diamond problem.<\/p>\n<p>Now I would like to combine the two classes into another class, so that both A() and B() are implemented, like this:<\/p>\n<pre><code>class DerivedC: public DerivedA, public DerivedB {\n     \/\/ Now DerivedA and DerivedB are combined\n};\n\n\/\/ Somewhere else in the code\nDerivedC c;\nc.A();\nc.B();\n<\/code><\/pre>\n<p><strong>The problem:<\/strong> Even though G++ compiles the code just fine, Eclipse gives an error: <code>The type 'DerivedC' must implement the inherited pure virtual method 'Base::B'<\/code>. When compiling with visual studio, I get 2 warnings:<\/p>\n<pre><code>warning C4250: 'DerivedC' : inherits 'DerivedB::DerivedB::B' via dominance\nwarning C4250: 'DerivedC' : inherits 'DerivedA::DerivedA::A' via dominance\n<\/code><\/pre>\n<p><strong>So the question is:<\/strong> what is the correct way of doing this? Does the code above produce undefined behavior?<\/p>\n<p><strong>Note:<\/strong> The title may be a little misleading, I have no idea what a good title for this question would be.<\/p>\n<ol>\n<li>\n<blockquote>\n<p><strong>What is the correct way of doing this? Does the code above produce undefined behavior?<\/strong><\/p>\n<\/blockquote>\n<p>The code is perfectly valid. There is no Undefined Behavior here.<br \/>\nAn unqualified call of <code>A()<\/code> through a <code>DerivedC<\/code> class object, will always call <code>DerivedA::A()<\/code>, while an unqualified call of <code>B()<\/code> through a <code>DerivedC<\/code> class object, will always call the <code>DerivedB::B()<\/code> instance.<\/p>\n<p>Visual C++ gives you a warning because your code uses a less commonly known feature of virtual Inheritance which may not be obvious to most common users and might surprise them. In this case, the <em>warning<\/em> should be taken as an <em>Informative Nitpick<\/em> rather than a warning.<\/p>\n<p>Note that the C++ Standard does not restrict compilers from emitting informative warnings for perfectly valid code. The documentation for warning C4250 gives an example which tells you why visual C++ chooses to give this warning.<\/p>\n<\/li>\n<li>\n<p>You might want to try this :<\/p>\n<pre><code>class DerivedC: public DerivedA, public DerivedB {\npublic:\n    using DerivedA::A;\n    using DerivedB::B;\n};\n<\/code><\/pre>\n<p>I can&#8217;t test with Eclipse or VC++ myself&#8230;<\/p>\n<\/li>\n<li>\n<p>I don&#8217;t know why a compiler would complain about any of this; this is just the standard mixin technique. Classes <code>Base<\/code>, <code>DerivedA<\/code> and <code>DerivedB<\/code> are abstract, and can&#8217;t be instantiated, but that&#8217;s usually the case for mixins. The whole point of a mixin is that it doesn&#8217;t implement all of the interface. And <code>DerivedC<\/code> implements both <code>A()<\/code> and <code>B()<\/code> through its inherited members.<\/p>\n<p>If a compiler refuses to compile this code, it is broken.<\/p>\n<p>As for warnings&#8230; a compiler is free to warn about anything it pleases:<\/p>\n<ul>\n<li>\n<p>There is no requirement that a class with virtual members have a virtual destructor. In practice, it&#8217;s usually a good idea, however (unless the destructor is protected), and a compiler warning is appropriate.<\/p>\n<\/li>\n<li>\n<p>The warnings from Visual Studio are &#8220;informative&#8221;, I guess, but this is the way the language is designed to work. And it&#8217;s certainly not something to avoid. For that matter, I don&#8217;t think that dominance actually plays a role here, since the functions in <code>Base<\/code> are pure virtual. What Visual Studios seems to be trying to say is that in <code>DerivedC<\/code>, the actual overload of <code>A()<\/code> is <code>DerivedA::A()<\/code>, and not <code>Base::A()<\/code>. Which seems to be what one would intuitively expect to me; the rules concerning dominance are really just a formal statement of what one would intuitively expect.<\/p>\n<\/li>\n<\/ul>\n<p>Anyway, I&#8217;d definitely turn the warning about dominance off. There&#8217;s certainly nothing to worry about in that respect. And I&#8217;d complain loudly about a compiler which didn&#8217;t compile the code.<\/p>\n<\/li>\n<li>\n<p>Your Base class is abstract : it can&#8217;t be instantiated. The B and A class are also abstract because they implement only one method.<\/p>\n<p>The two solutions are, in file <code>DerivedC.cpp<\/code><\/p>\n<pre><code>void DerivedC::A(){ \n   DerivedA::A();\n}\nvoid DerivedC::B(){\n   Derived:B();\n}\n<\/code><\/pre>\n<p>Or you can use <code>using<\/code> keyword in your header-file:<\/p>\n<pre><code>class DerivedC: public DerivedA, public DerivedB {\npublic:\n    using DerivedA::A;\n    using DerivedB::B;\n};\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 22:48:27. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I have a base class &#8216;Base&#8217;, which is a pure virtual class: class Base { public: virtual void A() = 0; virtual void B() = 0; virtual ~Base() { } \/\/ Eclipse complains that a class with virtual members must have virtual destructor }; I also have 2 other classes, one of them implements A() [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-842","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=842"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/842\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}