views:

125

answers:

2

I got into a problem with my classes, passing a const object (polymorphic structure) to an explicit constructor which takes a const reference to the base class of that polymorphic structure. Here is the sample (this is not from my code, it is for explanation here)

class Base 
{
...
}

class Derived:public Base
{
...
}

class Problem 
{
    Problem(const Base&);
...
}

void myFunction(const Problem& problem) 
{
    ...
}

int main() 
{
    //explicit constructor with non const object
    Derived d;
    Problem no1(d); //this is working fine 
    myFunction(no1);

    //implicit constructor with const object
    Problem no2=Derived(); //this is working fine, debugged and everything called fine
    myFunction(no2);   //is working fine

    //explicit constructor with const object NOT WORKING
    Problem no3(Derived());  //debugger jumps over this line (no compiler error here)
    myFunction(no3);   //this line is NOT COMPILING at all it says that:
    //no matching function for call to myFunction(Problem (&)(Derived))
    //note: candidates are: void MyFunction(const Problem&)
}

It seems that it is working fine with the second version (explicit constructor call for Problem) only if i explicitly cast the Derived object to its base class Base it like:

Problem(*(Base*)&Derived);

I do not realize the difference between calling impicitly and explicitly the constructor of the Problem class. Thank you!

+6  A: 

The problem is you aren't declaring an object, but a function:

Problem no3(Derived());
// equivalent to:
Problem no3(Derived); // with parameter name omitted

Use:

Problem no3((Derived()));
// extra parens prevent function-declaration interpretation
// which is otherwise required by the standard (so that the code isn't ambiguous)

This is a quirk of C's declaration syntax inherited by C++.

More examples:

void f(int(a)); /* same as: */ void f(int a);

void g() {
  void function(int);    // declare function
  void function(int());  // we can declare it again
  void function(int=42); // add default value
  function();            // calls ::function(42) ('function' in the global scope)
}
// 'function' not available here (not declared)

void function(int) {} // definition for declarations inside g above
Roger Pate
Damn, you are right. Many thanks! Though I got into the same problem some time ago I just didn't think of it now.
A: 

For future reference, this is a quirk known as the most vexing parse, see another StackOverflow thread as to the origin of this nickname.

Matthieu M.