views:

123

answers:

3

Ok, I guess that this is a very absurd/basic question, but still:

class m
{
public:
   void f(int ***);
  /***/
}
void m::f(int ***a = NULL)
{
  /***/
}

The call to f (as well as any function which has default values for all the arguments) doesn't accept 0 arguments. Why? How should I format the declaration then?

Thanks already.

+13  A: 

That works fine if the function definition is in the header file. The rule is that whoever is calling the function has to 'see' the default value.

So, I'm guessing you have the function definition in a separate source file. Assuming that's the case, just put the default in the function declaration (in the class):

class m
{
public:
   void f(int *** = 0);
  /***/
};

You'll also need to remove the default value from the function definition as you can only define the default in a single place (even if the value itself is the same).

R Samuel Klatchko
Oh yeah. Same file, but the call is before the definition. Easy to guess why! Though I had the fictitious perception (based on randomness, of course) that the problem was related to functions with all the parameters with default values.Cheers!
huff
+2  A: 

This will work:

class m
{
public:
   void f(int ***a = NULL);
};

void m::f(int ***a)
{
}
Eli Bendersky
+1  A: 

Default values in C++ are syntactic sugar; the compiler essentially inserts the argument for you at the callsite. This means that the compiler needs to know what the default value is, so it must be supplied by the function declaration.

This also means that if you have inheritance and virtual methods, the default values used are the ones from the static type (i.e., what type the compiler thinks the object is), not from the runtime type. For example:

class Base
{
public:
    virtual ~Base() { }

    virtual std::string foo(std::string s = "b") { return "Base:" + s; }
};

class Derived
: public Base
{
public:
   virtual std::string foo(std::string s = "d") { return "Derived:" + s; }
};

int main(void)
{
   Derived d;
   Base& b = d;
   std::cout << b.foo() << std::endl;
   return 0;
}

will print Derived:b, not Derived:d.

jamesdlin