How to join in a constructor three constructors with different signatures?

2

I have three constructors of a simple class A with different signatures but I wanted to make a single constructor that brings together the three constructors:

using namespace std ;
class A {
    private : int x, y;
    public :
        A();                 // constructeur I
        A(int abs);          // constructeur II
        A(int abs, int ord); // constructeur III
        A(const A &) ;       // constructeur IV
        ~A() ;              // destructeur
        void affiche();
} ;

A::A()
{
    x = 1 ;  y = 0 ;
    cout << "constructor I             : " << x << " " << y <<endl ;
}

A::A(int abs)
{
    x = abs ;  y = 0 ;
    cout << "constructor II            : " << x << " " << y <<endl ;
}

A::A(int abs, int ord)
{
    x = abs ;  y = ord ;
    cout << "constructor III           : " << x << " " << y << endl ;
}

main ()
{
    cout << "début main" << endl ;
    A a;
    A b(2);
    A c(10,20);
    A d = a ;
    A * adr = new A (3,3) ;
    fct (a, adr) ;
    A e(30,40);
    A tab[6]={4,c,0,e};
    for(int i=0;i<6;i++)
    tab[i].affiche();
    cout << "fin main" << endl ;
}

I've done

A::A(int abs =1 , int ord = 0)
{
    x = abs ;  y = ord ;
    cout << "constructeur III           : " << x << " " << y << endl ;
}

But it does not work. I also did an initialization in the class but it does not work either ... I've made a constructor that initializes the variables unless they give us the parameters they want:

A::A(int abs, int ord)
{
    x = 1;
    y = 0;
    x = abs ;  y = ord ;
    cout << "constructeur III           : " << x << " " << y << endl ;
}

And they give me the following errors:

$ g++ A_2.cpp -o A_2
A_2.cpp: In function ‘int main()’:
A_2.cpp:37:4: error: no matching function for call to ‘A::A()’
  A a;
    ^
A_2.cpp:37:4: note: candidates are:
A_2.cpp:14:1: note: A::A(int, int)
 A::A(int abs, int ord)
 ^
A_2.cpp:14:1: note:   candidate expects 2 arguments, 0 provided
A_2.cpp:3:7: note: A::A(const A&)
 class A {
       ^
A_2.cpp:3:7: note:   candidate expects 1 argument, 0 provided
A_2.cpp:38:7: error: no matching function for call to ‘A::A(int)’
  A b(2);
       ^
A_2.cpp:38:7: note: candidates are:
A_2.cpp:14:1: note: A::A(int, int)
 A::A(int abs, int ord)
 ^
A_2.cpp:14:1: note:   candidate expects 2 arguments, 1 provided
A_2.cpp:3:7: note: A::A(const A&)
 class A {
       ^
A_2.cpp:3:7: note:   no known conversion for argument 1 from ‘int’ to ‘const A&’
A_2.cpp:44:19: error: conversion from ‘int’ to non-scalar type ‘A’ requested
  A tab[6]={4,c,0,e};
                   ^
A_2.cpp:44:19: error: conversion from ‘int’ to non-scalar type ‘A’ requested
A_2.cpp:44:19: error: no matching function for call to ‘A::A()’
A_2.cpp:44:19: note: candidates are:
A_2.cpp:14:1: note: A::A(int, int)
 A::A(int abs, int ord)
 ^
A_2.cpp:14:1: note:   candidate expects 2 arguments, 0 provided
A_2.cpp:3:7: note: A::A(const A&)
 class A {
       ^
A_2.cpp:3:7: note:   candidate expects 1 argument, 0 provided
    
asked by ThePassenger 08.02.2017 в 13:49
source

2 answers

3

To merge the three constructors you have to leave a single signature:

class A {
    private : int x, y;
    public :
        // A();
        // A(int abs);
        // A(int abs, int ord);
        A(int abs =1 , int ord = 0);
        A(const A &);
        ~A();
        void affiche();
};

And, of course, a single implementation:

A::A(int abs, int ord)
{
    x = abs ;  y = ord ;
    cout << "constructeur III           : " << x << " " << y << endl ;
}

Important : Note that the default values are not indicated in the implementation.

    
answered by 08.02.2017 в 14:11
1

Normally, when you want to join constructors is to avoid possible errors derived from writing code (to more code, more possibility of errors). In your case, you want a builder to do three things at once:

  • Initialize by default.
  • Initialize member x .
  • Initialize members x e y .

It is not possible to create a constructor that does three different things.

Automatically generated builder.

But if we can save ourselves creating constructors manually and let the compiler do the work for us, the default constructor can be reduced to:

class A {
    //              vvv <-- Valor por defecto de x
    private : int x = 1, y = 0;
    //                     ^^^ <-- Valor por defecto de y
    public :
        A() = default; // Se usara la construccion por defecto de los miembros de A
        // ...
};

Notice that value has been assigned to A::x and A::y at the point of declaration, so it is not necessary that the default constructor has a body so we tell the compiler to generate it for us.

Delegated builder.

It is also possible to tell a constructor to delegate the initialization tasks in another constructor, in this way we can keep the constructor that receives two parameters and delegate from the constructor that receives a parameter:

class A {
    private : int x = 1, y = 0;
    public :
        A() = default; // Se usara la construccion por defecto de los miembros de A
        A(int abs) : A(abs, 0) {} // Se delega en el siguiente constructor 
        A(int abs, int ord) : x{abs}, y{ord} {} // Solo este constructor tiene codigo
        // ...
};
    
answered by 09.10.2017 в 11:37