Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Sorry, but the design seems to be flawed in several aspects. First,</p> <pre><code>typedef test_output&amp; (*test_function)(test_input&amp;); </code></pre> <p>calls for trouble. Don't return references to objects generated inside a function. The referenced object is destroyed, when the called function ends, so you will store in <code>result</code> the address of an object that does not exist anymore (dangling pointer). If you need polymorphic results, return them safely as <code>shared_ptr&lt;test_output&gt;</code>, which should also be the type of <code>result</code>.</p> <p>Concerning your list of questions (sorry for long answer):</p> <blockquote> <p>to bind the equivalent of operator==(*result, expected) to the equality operator for the dynamic types of these things;</p> </blockquote> <p>Yes, as you did. The equality test should be overridden for every class derived from <code>test_output</code>.</p> <blockquote> <p>to be able to indicate to the compiler that those types are derived from test_output;</p> </blockquote> <p>For comparing polymorphic objects for the left operand with polymorphic objects on the right hand side, welcome to the field of <em>multi-methods</em>. The problem boils down to: "When do you consider two objects as equal?" Should they have exactly the same type or can one belong to a subset of the other? Normally the <em>Liskov substitution principle</em> in object orientation means: A derived object can be substituted for a base object, since inheritance guarantees it has all base properties. To determine if <code>expected</code> to be of (at least) <code>to_derived</code> you need a <em>downcast</em>: </p> <pre><code>bool to_derived::operator==(const test_output&amp; expected) { if (to_derived* e = dynamic_cast&lt;to_derived*&gt;(&amp;expected)) { // compare all data fields, then return true; } return false; } </code></pre> <p>If you want to guarantee <code>expected</code> to be of <strong>exactly</strong> the same type, you should use <a href="http://en.wikipedia.org/wiki/Run-time_type_information" rel="nofollow">RTTI</a> first:</p> <pre><code> if (typeid(*this) != typeid(expected)) return false; </code></pre> <p>Derived objects are no consired of the same type. Maybe your compiler needs a switch to enable that.</p> <blockquote> <p>to be able to reassign result.</p> </blockquote> <p>Use a <code>shared_ptr&lt;test_output&gt;</code>, because it manages memory for dynamic objects.</p> <blockquote> <p>is it valid to use those function pointers as arguments to test_object? Their arguments can be dynamically typed but I don't know whether that means the function type itself has an automatic conversion to the function type taking and returning the respective base types. If not, how would I indicate a function of this dynamically-typed signature?</p> </blockquote> <p>The function pointers does not need any conversion. But your test framework seems to be incomplete, since it may work only for standalone functions. What about methods? I would suggest a templated solution. </p> <p>I would seriously consider looking for an <a href="http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B" rel="nofollow">existing unit testing framework</a>.</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.
    1. COYou say that `operator==(*result, expected)` *does* call `operator==(to_derived&, to_derived&)` and not `operator==(test_output&, test_output&)`? So if I have `to_derived: public test_output {int x;}` with the natural equality, and if `expected` has `x = 0` and `some_function_one` returns something with `x = 1`, does my code print the diagnostic or not? It seems to me it would not: the type of `*result` is determined at compilation to be `test_output` and so `operator==` is bound to `operator==(test_output&, test_output&)` whose obvious definition is always `true` (and ignores `x` anyway).
      singulars
    2. CO@Ryan : No, `(*result).operator==(expected)` is called because `test_output::operator==(const test_output& )` was declared as *member* function. However, it's a pure virtual (abstract) method. So you *have to* implement that operator for derived classes, otherwise you couldn't instantiate `to_derived` objects. A meaningful `to_derived::operator==` function body would then compare `this->x == e->x`. Since the base class `operator==` is declared *virtual*, the type of the left operand `*result` is determined at *runtime* (late binding). That's the basic idea of dynamic polymorphism.
      singulars
    3. COWhat do you know, I've been fooled. I thought that when you dereferenced a pointer to a base type it stopped being polymorphic, but a few quick tests show that what you say is true: it still gets the right virtual method. So basically, the `*` operator returns a reference bound to the pointed-to object.
      singulars
 

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