Unfit function signature : the following code still compiles. How is it possible? [duplicate]

Unfit function signature : the following code still compiles. How is it possible? [duplicate]
typescript
Ethan Jackson

Let's have 3 files :

  • Personne.h :
#include <iostream> #include <string> using namespace std; struct Personne { string nom; string prenom; int age; Personne(); Personne(string nom, string prenom, int age); Personne(Personne const*); virtual ~Personne(); void set(Personne); };
  • Personne.cpp :
#include "Personne.h" Personne::Personne() : nom(NULL) {} Personne::Personne(string nom0, string prenom0, int age0) : nom(nom0), prenom(prenom0), age(age0) {} Personne::Personne(Personne const* copied) : nom(copied->nom), prenom(copied->prenom), age(copied->age) {} Personne::~Personne() {} void Personne::set(Personne copied) { cout << "copied.nom = " << copied.nom << endl; nom = copied.nom; prenom = copied.prenom; age = copied.age; }
  • main.cpp :
#include "Personne.h" int main() { cout << "Dinguerie !" << endl; Personne moi("Gustin", "Didier", 34); Personne* moi_pointeur(&moi); moi_pointeur->set(moi_pointeur); moi_pointeur->set(*moi_pointeur); return 0; }

In main.cpp, line 8 should generate a compilation error as it doesn't fit the signature of the function declared in Personne.h and implemented in Personne.cpp. Line 8 uses the set function with Personne* instead of Personne as argument. But no error at compilation and moreover line 8 do exactly the same as the line 9 at execution.

Can someone explain to me why this code compiles ?

Answer

C++ allows one implicit conversion per argument when matching function arguments, as Personne(Personne const*) isn't marked explicit it is used to convert your Personne* to a new Personne object.

moi_pointeur->set(moi_pointeur); is automatically transformed to moi_pointeur->set(Personne(moi_pointeur));

Changing your class to:

struct Personne { string nom; string prenom; int age; Personne(); Personne(string nom, string prenom, int age); explicit Personne(Personne const*); virtual ~Personne(); void set(Personne); };

results in the compiler error you expect.

In general it's a good idea to mark all single argument constructors as explicit unless you want automatic conversions to apply.

Related Articles