C++ Error: Call of overloaded 'Function' is ambiguous

I've got the below error but it was good learning though. 

/usr/include/c++/9/ext/new_allocator.h:145:20: error: call of overloaded 
                          Cadbury(int, int) is ambiguous
  145 |  noexcept(noexcept(::new((void *)__p)
      |                    ^~~~~~~~~~~~~~~~~~
  146 |        _Up(std::forward<_Args>(__args)...)))
      |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:2:
Chocolate.h:58:2: note: candidate: Cadbury::Cadbury(float, float, int)
   58 |  Cadbury(float x, float y, int d=0);
      |  ^~~~~
Chocolate.h:57:2: note: candidate: Cadbury::Cadbury(float, float)
   57 |  Cadbury(float x, float y);
      |  ^~~~~
make: *** [makefile:14: main] Error 1

 


My program is shown below:

#include <iostream>
#include "Chocolate.h"
using namespace std;
        
int main()
{
  
    Cadbury c1(-1, -2);
    Cadbury c2(10, -2);
    return 0; 
}

/***************************************************************************/

//Chocolate.cpp
#include "Chocolate.h"
using namespace std;

Chocolate::Chocolate() {
        cout << " Chocolate ()" << endl; 
        setFlavor(0);
}

Chocolate::Chocolate(int sugar) {
        cout << " Chocolate (" << sugar << ")" << endl;
        setFlavor(sugar); 
}
/***************************************************************************/

//Cadbury.cpp
#include "Chocolate.h"
using namespace std;

Cadbury::Cadbury(float x, float y, int sugar) {
        cout << " Cadbury (" << x << " , " << y << " , " << sugar << ")" << endl;
        xCFirst = x;
        yCSecond = y;
        setFlavor(sugar); 
}

Cadbury::Cadbury(float x, float y) {
        cout << " Cadbury (" << x << " , " << y << ")" << endl;
        xCFirst = x;
        yCSecond = y;
}

/***************************************************************************/
//Cadbury.h
#ifndef CADBURY_H_
#define CADBURY_H_

#include <iostream>
#include <memory>

class Cadbury; // forward declaration/reference

class Chocolate {

public:
        Chocolate();
        Chocolate(int sugar);
        bool setFlavor(int sugar);
};

class Cadbury : public Chocolate {
  
public:
     Cadbury(float x, float y);
     Cadbury(float x, float y, int sugar=0);

private:
       
     float xCFirst;
     float yCSecond;

};

#endif /* CADBURY_H_ */


When I called Cadbury c1(-1, -2) two calls of constructor match:  

Cadbury(float x, float y);

Cadbury(float x, float y, int sugar=0); 

Second constructor matches because third argument has default value 0, so it is equivalent to call Cadbury c1(-1, -2, 0). 

Compiler cannot choose which one to call. So, I made the following changes/separation in my Cadbury.h file.

Method 1 (Removing the default argument initial value)

#include <iostream>
#include "Chocolate.h"
using namespace std;
        
int main()
{
  
    Cadbury c1(-1, -2);
    Cadbury c2(10, -2);
    return 0; 
}

/***************************************************************************/

//Chocolate.cpp
#include "Chocolate.h"
using namespace std;

Chocolate::Chocolate() {
        cout << " Chocolate ()" << endl; 
        setFlavor(0);
}

Chocolate::Chocolate(int sugar) {
        cout << " Chocolate (" << sugar << ")" << endl;
        setFlavor(sugar); 
}
/***************************************************************************/

//Cadbury.cpp
#include "Chocolate.h"
using namespace std;

Cadbury::Cadbury(float x, float y) {
        cout << " Cadbury (" << x << " , " << y << ")" << endl;
        xCFirst = x;
        yCSecond = y;
}

Cadbury::Cadbury(float x, float y, int sugar) {
        cout << " Cadbury (" << x << " , " << y << " , " << sugar << ")" << endl;
        xCFirst = x;
        yCSecond = y;
        setFlavor(sugar); 
}


/***************************************************************************/
//Cadbury.h
#ifndef CADBURY_H_
#define CADBURY_H_

#include <iostream>
#include <memory>

class Cadbury; // forward declaration/reference

class Chocolate {

public:
        Chocolate();
        Chocolate(int sugar);
        bool setFlavor(int sugar);
};

class Cadbury : public Chocolate {
  
public:
     Cadbury(float x, float y);
     Cadbury(float x, float y, int sugar);

private:
       
     float xCFirst;
     float yCSecond;

};

#endif /* CADBURY_H_ */

Cadbury class has these 2 constructors. 

Cadbury(float x, float y);

Cadbury(float x, float y, int sugar);  

I also added the default constructor in addition to the above.

Cadbury();

Output

Chocolate () 
setFlavor(0) 
Cadbury (0 , 0 , 0)
setFlavor(0) 

With this method, Cadbury constructor with 3 arguments is executed even the c1 object has only 2 arguments. I find that it is not necessary to have the constructor cadbury with 2 arguments itself. 

But, if remove the constructor Cadbury(float x, float y);, it will lead to this error because it doesn't know what would be the value for the third argument. We also don't have the default value for the third argument.

 error: no matching function for call to ‘Cadbury::Cadbury(float, float)

Method 2 

So, I decided to simplify and sort this problem with default value (0) with maximum arguments (3 arguments) passed. 

#include <iostream>
#include "Chocolate.h"
using namespace std;
        
int main()
{
  
    Cadbury c1(-1, -2);
    Cadbury c2(10, -2);
    return 0; 
}

/***************************************************************************/

//Chocolate.cpp
#include "Chocolate.h"
using namespace std;

Chocolate::Chocolate() {
        cout << " Chocolate ()" << endl; 
        setFlavor(0);
}

Chocolate::Chocolate(int sugar) {
        cout << " Chocolate (" << sugar << ")" << endl;
        setFlavor(sugar); 
}
/***************************************************************************/

//Cadbury.cpp
#include "Chocolate.h"
using namespace std;

Cadbury::Cadbury(float x, float y, int sugar) {
        cout << " Cadbury (" << x << " , " << y << " , " << sugar << ")" << endl;
        xCFirst = x;
        yCSecond = y;
        setFlavor(sugar); 
}


/***************************************************************************/
//Cadbury.h
#ifndef CADBURY_H_
#define CADBURY_H_

#include <iostream>
#include <memory>

class Cadbury; // forward declaration/reference

class Chocolate {

public:
        Chocolate();
        Chocolate(int sugar);
        bool setFlavor(int sugar);
};

class Cadbury : public Chocolate {
  
public:
     Cadbury(float x, float y, int sugar=0);

private:
       
     float xCFirst;
     float yCSecond;

};

#endif /* CADBURY_H_ */

Output

Chocolate () 
setFlavor(0) 
Cadbury (0 , 0 , 0)
setFlavor(0) 

Method 3

I also found there were two Chocolate constructors unnecessarily, so, I wanted to have only one. 

#include <iostream>
#include "Chocolate.h"
using namespace std;
        
int main()
{
  
    Cadbury c1(-1, -2);
    Cadbury c2(10, -2);
    return 0; 
}

/***************************************************************************/

//Chocolate.cpp
#include "Chocolate.h"
using namespace std;

Chocolate::Chocolate(int sugar) {
        cout << " Chocolate (" << sugar << ")" << endl;
        setFlavor(sugar); 
}
/***************************************************************************/

//Cadbury.cpp
#include "Chocolate.h"
using namespace std;

Cadbury::Cadbury(float x, float y, int sugar) : Chocolate(sugar) {
        cout << " Cadbury (" << x << " , " << y << " , " << sugar << ")" << endl;
        xCFirst = x;
        yCSecond = y;
}


/***************************************************************************/
//Cadbury.h
#ifndef CADBURY_H_
#define CADBURY_H_

#include <iostream>
#include <memory>

class Cadbury; // forward declaration/reference

class Chocolate {

public:
        Chocolate(int sugar);
        bool setFlavor(int sugar);
};

class Cadbury : public Chocolate {
  
public:
     Cadbury(float x, float y, int sugar = 0);

private:
       
     float xCFirst;
     float yCSecond;

};

#endif /* CADBURY_H_ */

Output

Chocolate (0) 
setFlavor(0) 
Cadbury (0 , 0 , 0)

It worked like charm. I think you had very good time learning this!!

Comments