2010-01-16 10 views
4

Je suppose que cela est une question très absurde/de base, mais encore:C++ ... lorsque tous les arguments ont des valeurs par défaut

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

L'appel à f (ainsi que toute fonction qui a des valeurs par défaut pour tous les arguments) n'accepte pas 0 arguments. Pourquoi? Comment dois-je formater la déclaration alors?

Répondre

13

Cela fonctionne correctement si la définition de la fonction se trouve dans le fichier d'en-tête. La règle est que quiconque appelle la fonction doit "voir" la valeur par défaut. Donc, je suppose que vous avez la définition de la fonction dans un fichier source séparé. En supposant que ce soit le cas, il suffit de mettre la valeur par défaut dans la déclaration de fonction (dans la classe):

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

Vous aurez également besoin de supprimer la valeur par défaut de la définition de la fonction que vous ne pouvez définir la valeur par défaut en une seule placer (même si la valeur elle-même est la même).

+0

Oh ouais. Même fichier, mais l'appel est avant la définition. Facile à deviner pourquoi! Bien que j'avais la perception fictive (basée sur le hasard, bien sûr) que le problème était lié aux fonctions avec tous les paramètres avec des valeurs par défaut. À la votre! – huff

2

Cela fonctionne:

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

void m::f(int ***a) 
{ 
} 
2

valeurs par défaut dans C++ sont le sucre syntaxique; le compilateur insère essentiellement l'argument pour vous sur le site d'appel. Cela signifie que le compilateur doit savoir quelle est la valeur par défaut, donc il doit être fourni par la déclaration de fonction. Cela signifie également que si vous avez des méthodes d'héritage et des méthodes virtuelles, les valeurs par défaut utilisées sont celles du type statique (c'est-à-dire, le type du compilateur) et non du type d'exécution. Par exemple:

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; 
} 

imprimera Derived:b, pas Derived:d.