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]

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.

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles