Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You are asking a question and providing a code example that fails but for a different reason. From the wording of your question:</p> <p><strong>Why are references/pointers required for polymorphism?</strong></p> <pre><code>struct base { virtual void f(); }; struct derived : public base { virtual void f(); }; void call1( base b ) { b.f(); // base::f } void call2( base &amp;b ) { b.f(); // derived::f } int main() { derived d; call1(d); call2(d); } </code></pre> <p>When you use pass-by-value semantics (or store derived elements in a base container) you are creating copies of type <code>base</code> of the elements of type <code>derived</code>. That is called <strong>slicing</strong>, as it resembles the fact that you have a <code>derived</code> object and you <em>slice/cut</em> only the <code>base</code> subobject from it. In the example, <code>call1</code> does not work from the object <code>d</code> in main, but rather with a temporary of type <code>base</code>, and <code>base::f</code> is called.</p> <p>In the <code>call2</code> method you are passing a reference to a <code>base</code> object. When the compiler sees <code>call2(d)</code> in main it will create a reference to the <code>base</code> subobject in <code>d</code> and pass it to the function. The function performs the operation on a reference of type <code>base</code> that points to an object of type <code>derived</code>, and will call <code>derived::f</code>. The same happens with pointers, when you get a <code>base *</code> into a <code>derived</code> object, the object is still <code>derived</code>.</p> <p><strong>Why can I not pass a container of <code>derived</code> pointers to a function taking a container of <code>base</code> pointers?</strong></p> <p>_Clearly if <code>derived</code> are <code>base</code>, a container of <code>derived</code> <em>is</em> a container of <code>base</code>.</p> <p>No. Containers of <code>derived</code> are not containers of <code>base</code>. That would break the type system. The simplest example of using a container of <code>derived</code> as container of <code>base</code> objects breaking the type system is below.</p> <pre><code>void f( std::vector&lt;base*&gt; &amp; v ) { v.push_back( new base ); v.push_back( new another_derived ); } int main() { std::vector&lt;derived*&gt; v; f( v ); // error!!! } </code></pre> <p>If the line marked with error was allowed by the language, then it would allow the application to insert elements that are not of type <code>derived*</code> into the container, and that would mean lots of trouble...</p> <p><strong>But the question was about containers of value types...</strong></p> <p>When you have containers of value types, the elements get copied into the container. Inserting an element of type <code>derived</code> into a container of type <code>base</code> will make a copy of the subobject of type <code>base</code> within the <code>derived</code> object. That is the same <strong>slicing</strong> than above. Besides that being a language restriction, it is there for a good reason, when you have a container of <code>base</code> objects, you have space to hold just <code>base</code> elements. You cannot store bigger objects into the same container. Else the compiler would not even know how much space to reserve for each element (what if we later extend with an even-bigger type?).</p> <p>In other languages it may seem as this is actually allowed (Java), but it is not. The only change is in the syntax. When you have <code>String array[]</code> in Java you are actually writting the equivalent of <code>string *array[]</code> in C++. All non-primitive types are references in the language, and the fact that you do not add the <code>*</code> in the syntax does not mean that the container holds <em>instances of String</em>, containers hold <em>references</em> into Strings, that are more related to c++ pointers than c++ references.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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