Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>While rethinking on the question I just realized of another problem you have. Polymorphic behavior can only be achieved through pointers and/or references. Trying to do so with values produces what is called <em>slicing</em>, where the original derived object is converted (copied) into a base object loosing all the extra information.</p> <p>The common example of slicing is this one:</p> <pre><code>class Base { public: virtual void polymorphic() { std::cout &lt;&lt; "Base" &lt;&lt; std::endl; } }; class Derived : public Base { public: virtual void polymorphic() { std::cout &lt;&lt; "Derived" &lt;&lt; std::endl; } }; void f( Base b ) { b.polymorphic(); } int main() { Derived d; f( d ); // prints Base } </code></pre> <p>Now, the original question deals with conversion of pointer types and I answered <a href="https://stackoverflow.com/questions/1007390/is-it-possible-to-make-pointers-to-distinct-template-types-convertible/1008183#1008183">before</a>. I believe that your code presents a variant of the <em>slicing</em> problem. We can play a little with the <em>undefined behavior</em> of forcing pointer conversions from unrelated types:</p> <pre><code>// same Base and Derived definitions as above template &lt;typename T&gt; struct Holder { T data; }; int main() { Holder&lt;Derived&gt; derived; Holder&lt;Derived&gt;* derived_ptr = &amp;derived; Holder&lt;Base&gt;* base_ptr = reinterpret_cast&lt;Holder&lt;Base&gt;* &gt;( derived_ptr ); // undefined!!! std::cout &lt;&lt; "derived_ptr=" &lt;&lt; derived_ptr &lt;&lt; ", base_ptr=" &lt;&lt; base_ptr &lt;&lt; std::endl; base_ptr-&gt;data.polymorphic(); // prints Base } </code></pre> <p>First of all, this is undefined behavior according to the standard... but bear with me. We can try to work what a common compiler could implement. We have an object of type <em>Holder</em>, and a pointer to it (<em>derived_ptr</em>), now we reinterpret the pointer as a pointer to <em>Holder</em>. At this point <em>base_ptr</em> and <em>derived_ptr</em> have the same value, they point to the same address (check the output).</p> <p>In the last step we access the data field of the <em>Holder</em> stored at <em>&amp;derived</em>, and we call the virtual function * polymorphic()* on it... but in <em>Holder</em>, the <em>data</em> field is not a reference or pointer, it is an element of type <em>Base</em>, so the compiler can decide that it will call the <em>Base</em> version of it, and it so does in g++ 4.0.</p> <p>This is all <em>undefined behavior</em>, so try it with your compiler of choice, it may end up with the same or different outcomes.</p> <p>If you change the template definition to store a pointer, then you get the <em>expected</em> polymorphic behavior. That is, expected in this case, knowing the memory footprint of the objects at hand. Not that you can <em>expect</em> anything from the unexpected <em>undefined behavior</em>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload