Constructor Overloading

Pages: 12
Hi Everyone,

I'm trying to instantiate an object using constructor overloading, but it is not working.

I have the following code:

Vehicle.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include <iostream>
using namespace std;

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        //Default constructor
        Vehicle(int wheels=4, int doors=4)
        {
                numWheels = wheels;
                numDoors  = doors;
        }

        // Setters
        void setNumWheels(int wheels) { numWheels = wheels; }
        void setNumDoors( int doors)  { numDoors  = doors;  }

        // Getters
        int getNumWheels() { return numWheels; }
        int getNumDoors()  { return numDoors ; }

        void printNumWheels()
        {
                cout << "This car has " << numWheels << "wheels" << endl;
        }
};


Vehicle.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef __VEHICLE_INCLUDED__
#define __VEHICLE_INCLUDED__

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        Vehicle(int wheels, int doors) {}
        void setNumWheels(int wheels) {}
        void setNumDoors(int doors)   {}

        int getNumWheels() {}
        int getNumDoors()  {}
        void printNumWheels() {}
};

#endif 


vehicle-test.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "Vehicle.h"

using namespace std;

int main()
{
        Vehicle jaguar;

        jaguar.setNumWheels(4);

//      cout << "Jaguar has " << jaguar.getNumWheels() << " wheels and ";
//      cout << 4 << " doors" << endl;

        jaguar::printNumWheels();

        return 0;
}


Vehicle.cpp compiles without error. vehicle-test.cpp does not compile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
./vehicle-test.cpp: In function ‘int main()’:
./vehicle-test.cpp:8:10: error: no matching function for call to ‘Vehicle::Vehicle()’
  Vehicle jaguar;
          ^
./vehicle-test.cpp:8:10: note: candidates are:
In file included from ./vehicle-test.cpp:2:0:
./Vehicle.h:11:2: note: Vehicle::Vehicle(int, int)
  Vehicle(int wheels, int doors) {}
  ^
./Vehicle.h:11:2: note:   candidate expects 2 arguments, 0 provided
./Vehicle.h:4:7: note: Vehicle::Vehicle(const Vehicle&)
 class Vehicle
       ^
./Vehicle.h:4:7: note:   candidate expects 1 argument, 0 provided
./vehicle-test.cpp:15:2: error: ‘jaguar’ is not a class or namespace
  jaguar::printNumWheels();
  ^


My question is - with function overloading, why does the compiler complain that there is no matching function? The C++ tutorial I am reading on the subject of constructors ( http://www.learncpp.com/cpp-tutorial/85-constructors/ ) explains that I should be able to do this?

Many thanks
Last edited on
Try getting rid of your constructor's default arguments in Vehicle.cpp and moving them to Vehicle.h.
*Try creating a constructor that takes 0 arguments since you created an object that has no argument (Vehicle jaguar;).

EG: Vehicle()
{
numWheels = 0;
numDoors = 0;
}

*And also try replacing what you have in Vehicle.h with what you have for Vehicle.cpp
You never overloaded the constructor as you have just one constructor, which has two arguments.
See this:
vehicle.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
#ifndef __VEHICLE_INCLUDED__
#define __VEHICLE_INCLUDED__

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        Vehicle(int wheels, int doors) {}
        Vehicle() {}     //Constructor overloaded
        void setNumWheels(int wheels) {}
        void setNumDoors(int doors)   {}

        int getNumWheels() {}
        int getNumDoors()  {}
        void printNumWheels() {}
};

#endif 
}


vehicle.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
#include <iostream>
using namespace std;

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        //Default constructor
        Vehicle(int wheels=4, int doors=4)
        {
                numWheels = wheels;
                numDoors  = doors;
        }
        //Default constructor overloaded
        Vehicle ()
        {
               numWheels = 0;
               numDoors = 0;
         }

        // Setters
        void setNumWheels(int wheels) { numWheels = wheels; }
        void setNumDoors( int doors)  { numDoors  = doors;  }

        // Getters
        int getNumWheels() { return numWheels; }
        int getNumDoors()  { return numDoors ; }

        void printNumWheels()
        {
                cout << "This car has " << numWheels << "wheels" << endl;
        }
};
}


vehicle-test.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
#include <iostream>
#include "Vehicle.h"

using namespace std;

int main()
{
        Vehicle jaguar;

        jaguar.setNumWheels(4);

//      cout << "Jaguar has " << jaguar.getNumWheels() << " wheels and ";
//      cout << 4 << " doors" << endl;

        jaguar.printNumWheels();  //Line 16 of vehicle-test.cpp, you can't use    ::(scope resolution operator), you have to use .(dot, member access operator) since it isn't a static member function

        return 0;
}
}

Note: You may have more than one constructor as long as the parameters are different,so that when a call enters an object scope, it will know which constructor to execute. This is overloadding, not just having a single constructor.


Thanks for that. That is how I have always understood constructor overloading. I deliberately did not create a constructor that takes no arguments, as according to the instructions on the constructor tutorial (see original post), my code should have worked? According to that web page, I can have a single constructor that adapts its behaviour accordingly, therefore doing away with the traditional overloading.

When I tried to copy that constructor as shown in the examples, my code fails.

I wrote:
Try getting rid of your constructor's default arguments in Vehicle.cpp and moving them to Vehicle.h.

Did you try this yet?
Okay I have moved the arguments into the header file and now have:

Vehicle.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        //Default constructor
        Vehicle() {}

        // Setters
        void setNumWheels(int wheels) { numWheels = wheels; }
        void setNumDoors( int doors)  { numDoors  = doors;  }

        // Getters
        int getNumWheels() { return numWheels; }
        int getNumDoors()  { return numDoors ; }

        void printNumWheels()
        {
                cout << "This car has " << numWheels << "wheels" << endl;
        }
};


Vehicle.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef __VEHICLE_INCLUDED__
#define __VEHICLE_INCLUDED__

class Vehicle
{
        int numWheels;
        int numDoors;

        public:

        Vehicle(int wheels, int doors)
        {
                numWheels = wheels;
                numDoors  = doors;
        }

        Vehicle() { }

        void setNumWheels(int wheels) {}
        void setNumDoors(int doors)   {}

        int getNumWheels() {}
        int getNumDoors()  {}
        void printNumWheels() {}
};

#endif 


vehicle-test.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "Vehicle.h"

using namespace std;

int main()
{
        Vehicle jaguar;

        jaguar.setNumWheels(4);

//      cout << "Jaguar has " << jaguar.getNumWheels() << " wheels and ";
//      cout << 4 << " doors" << endl;

        jaguar.printNumWheels();

        return 0;
}


The code compiles, but produces no output. So there are the two issues which I am trying to resolve: 1) Why I was not able to get the constructor to work as defined in the tutorial page, and 2) why Vehicle::printNumWheels() is generating no output.

Many thanks for your help
I think @long double main means to move the default arguments, not the default constructor, like this:
1
2
3
4
5
6
7
8
// vehicle.h

//...
        public:
        Vehicle(int wheels = 4; int doors = 4);
//      Vehicle() {}

//... 

1
2
3
4
5
6
7
8
9
// vehicle.cpp
#include "vehicle.h"

Vehicle::Vehicle(int wheels, int doors) {
    numWheels = wheels;
    numDoors = doors;
}

//... 


Which reminds me: Why are you defining the class twice? Why don't you just define the class in the header file and then implement it in the source file? That means that if you change the layout of your class you only need to modify it once, rather than twice, which can help prevent bugs (like this one).
Last edited on
why Vehicle::printNumWheels() is generating no output.

You now have two different definitions of your Vehicle class - one in Vehicle.h, and one in Vehicle.cpp. vehicle-test.cpp includes Vehicle.h, so uses the definition of the class supplied in Vehicle.h.

Have a look at the way you've defined Vehicle::printNumWheels() in Vehicle.h. What would you expect it to print out?

EDIT: I'm surprised your compiler isn't giving you an error about the Vehicle class being defined twice. Are you linking Vehicle.cpp into your build?
Last edited on
Oh, I didn't realise that I was technically defining the class twice. I agree, it should be defined in the header and then implemented in the source. Is that not what I have done? I'm just starting off here so I'm trying to understand best practice, but I feel a bit confused now.

So if I make Vehicle.h define the constructor as
 
Vehicle(int wheels = 4; int doors = 4);


Does this then allow me to use the behaviour as shown in the tutorial, and instantiate a Vehicle with 0,1, or 2 arguments?


Have a look at the way you've defined Vehicle::printNumWheels() in Vehicle.h. What would you expect it to print out?


I'm not sure I understand. Vehicle.h defines the method printNumWheels as having a void return type, which is correct, as it does not return anything. Where I have implemented the method in Vehicle.cpp it prints out to the console the number of wheels that a particular car has ?

Many thanks
You have implemented `printNumWheels()' in Vehicle.h
void printNumWheels() {} note the braces

A declaration would be void printNumWheels();
Ah I see, thanks. So when declaring a function in the header file, leave off the curly braces!
Now that we have cleared up the fact that I was implementing functions within the header, I am trying to work out how to get that arrangement with a single constructor that can take multiple numbers of parameters can work, as shown in the tutorial page.

Can anyone suggest how this Vehicle code should be arranged to allow that?

Many thanks


Ah I see, thanks. So when declaring a function in the header file, leave off the curly braces!

In the header file, you can either:

1) Define the function, giving the complete code for the function's implementation. you do this, you use the curly braces.

OR:

2) Declare the function, giving just the name, the types of the arguments, and the return type. If you do this, you don't use the curly braces, and you need to put the definition in a .cpp file.

Okay, got it. I will always try to declare the function in the header and then define it in the .cpp :-)
Cool - that's usually the better of the two options.
I'm now getting failures during linking:

1
2
3
4
5
6
$ g++ ./Vehicle.o ./vehicle-test.o -o test
./vehicle-test.o: In function `main':
vehicle-test.cpp:(.text+0x79): undefined reference to `Vehicle::Vehicle()'
vehicle-test.cpp:(.text+0x87): undefined reference to `Vehicle::setNumWheels(int)'
vehicle-test.cpp:(.text+0x90): undefined reference to `Vehicle::printNumWheels()'
collect2: ld returned 1 exit status


I'm not sure why it is unable to find those references.

vehicle-test.cpp:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "Vehicle.h"

using namespace std;

int main ()
{
    Vehicle jaguar;
    jaguar.setNumWheels(4);
    jaguar.printNumWheels();
}


Vehicle.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef __VEHICLE_INCLUDED__
#define __VEHICLE_INCLUDED__

class vehicle
{
    int numWheels;
    int numDoors;

    public:
    Vehicle();

    void setNumWheels(int wheels);
    void setNumDoors(int doors);
    int getNumWheels();
    int getNumDoors();
    void printNumWheels();
};
#endif 


Vehicle.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

class Vehicle
{
    int numWheels;
    int numDoors;

    public:

    Vehicle() { }

    void setNumWheels(int wheels) { numWheels = wheels; }
    void setNumDoors(int doors)  { numDoors = doors; }

    int getNumWheels() { return numWheels; }
    int getNumDoors()  { return numDoors; }

    void printNumWheels()
    {
        cout << "This car has " << numWheels << " wheels" << endl;
    } 
};
Last edited on
You still have two class definitions for Vehicle. The following block:

1
2
3
4
class Vehicle
{
  // Stuff
};


is a class definition. You're defining a class called Vehicle in Vehicle.h, and another class also called Vehicle in Vehicle.cpp.

The one in the header doesn't contain definitions for the methods, just declarations. Presumably that's the one the linker is trying to use, hence the link errors.

Is your compiler not warning you about the double definition of the class? If not, are you absolutely sure you're linking Vehicle.cpp into your program?


EDIT: As ne555 spotted below, you're not actually defining the same class twice - you're defining a class called vehicle, and one called Vehicle.
Last edited on
cASe SenSItiVe
class vehicle Vehicle.h
class Vehicle Vehicle.cpp

Why are you defining the class twice? Why don't you just define the class in the header file and then implement it in the source file?
cASe SenSItiVe

D'oh! Can't believe I didn't spot that...
Pages: 12