When we learned about c++ functions,
we learned that we can supply default values as parameters to functions.
The same applies to class methods and class constructors.
In many cases, we can reduce the number of overloaded
constructors by providing default constructor parameters.
The same rules that we learned when working with default function parameters
apply to constructors.
Let's continue working with our player class.
We can actually just have one constructor
that does everything that we did with the three constructors previously.
You can't always have default parameters in class design, but many times you can.
Here's an example where it makes perfect sense.
Notice that the player class now has only a single constructor,
and that constructor has three arguments:
the name, health and xp of the player.
But in this example, we're providing default parameter values for all the parameters.
For the player's name, the default is the string none.
And for health in xp, the defaults are 0.
These default parameters are declared in the constructor declaration
in the class as shown.
Now when we implement the constructor,
we can implement it exactly as we implemented the three argument constructor in the previous videos.
Here you can see the implementation for the single constructor.
Notice that you don't supply the default parameters here.
We can simply use an initializer list to initialize the class attributes,
and the compiler will take care of providing the default values as needed.
This is very handy and results in less code to write
which means less code to test which means less code that could have errors.
Since this single constructor is doing the job of several constructors,
we have to be careful not to declare ambiguous constructors.
For example, what would happen if we implemented a no argus constructor
in addition to the one we see on this slide?
Well, we'd get a compiler error because the compiler wouldn't know which one to call.
In this example, we're creating empty,
frank and villain objects, as we did before. But take a look at hero.
We didn't have a two args constructor in the previous version of the player class,
but we do in this version. That's pretty cool.
Now let's modify our existing player class in the IDE so you can see how this works.
Hi, so I'm in the IDE, and I'm in the section 13 workspace
in the DefaultConstructorParameters project.
And what we've got is the player class as we defined it in the last few videos
where we've got our three constructors and here we're using delegating constructors
and down here we're using an initializer,
a constructor initializer list right here on line 32.
What I want to do is I want to get rid of -- I want to simplify this.
I want to get rid of some of these overloaded constructors
and use default parameters instead as we did with the slides.
So what I want to do is just get rid of all these constructors right here.
I just want to end up with one single constructor and there it is,
player with three arguments.
And what I'd like to do is supply some default parameter values for these.
Now you can't always do this when you're doing class design,
but sometimes you can. And when you can, you should because it really simplifies your code.
So in this case, I'm going to default
the name of the
player to none.
I'm going to default the health value to 0.
I'm going to default the xp value to 0.
Okay. So that's what we've got now.
There is my three default parameters.
Now these two constructors go away, so I'm just going to get rid of them right here.
And this constructor was which is our three arg constructor that
matches the signature for this one, we really don't have to do anything to it.
These default parameters will automatically be supplied
by the compiler when we need them.
Okay. So now what we've got is
same code we had before. Now I'll put a break point here. It's the only constructor being called,
so we'll definitely see it being called.
And I'm going to create an empty object here. So again, it's a player object.
And I'm not supplying any initialization information here.
So what's going to happen is all three of those default parameters will be substituted.
And I'll end up with an object none 0 0, which is exactly what I want.
In the case of frank,
I'll end up with frank 0 0, because the none will be overridden by the frank.
In the last one, all three of my initializers will be supplied so, it'll be villain 100 and 55.
Now there's another one that we've got here as well,
which is this one. Let's just say player hero.
And suppose I want to say this is hero,
and it's 100 for the health.
Now in this case, that hero object will have the name hero
100 for health since the xp wasn't supplied.
The xp will get the value of 0.
Now this is a constructor we didn't have before. We didn't have a two args constructor.
Okay. So let's run this, and we'll walk through it.
And I'll put the out screen over here. The output screen will be real simple.
We'll just get this three args constructor message being displayed all the time,
that's the only constructor we have. Okay. So let's start here.
Here's my player empty,
right. This is a no args constructor that's going to be called.
Well, we don't have a no argus constructor.
But we've got this constructor that expects three arguments,
and we're telling the compiler to default those three if it has to.
In this case, it has to.
So what it's going to do is it's going to provide none 0 0 and call this guy right here.
Okay. So let's step through this, and we'll see --
we're in the constructor now, you can see that that constructor did indeed get called.
We're on line 20 right now.
And we're going to initialize it. We're going to display three args constructor over here.
And then we're back to main.
At this point, empty should have none 0 0 which is exactly what we've got.
Now in the case of the player frank,
I expect it to have frank 0 0. So let's walk through that.
There I am at line 20 again.
I'll step through it a couple more times. Now we'll see three args constructor again
being displayed.
I'm back in my main. And if I look at frank here,
we see frank 0 0 which is again what we expected.
Now the hero object we expect to have hero 100 and 0.
So let's walk through that.
We're in that constructor right now. We're in the initialization list.
And we'll print out the three args constructor message one more time.
We're done initializing that object now. So if we look at hero,
we should see hero 100 0,
which is again exactly what I expected.
Now in the last case, I'm providing all three of the initializers
So what we expect is villain 155, right.
None of the default parameters here will be used. So let's try that out. We'll walk through it,
and we're back in main now. If we look at villain,
we'll have villain 155, just what we want.
Okay. So that gives you an idea of
how we can use default constructor parameters,
which is really really handy. It'll definitely simplify your code.
As I said before, you can't always use these.
Sometimes it really doesn't make sense to provide
default parameter values. You really want you know the user to explicitly
provide all of them.
But sometimes you can. And when you can, they come real handy.
Now just before we wrap up this video
let's see what happens if we supply
a constructor and c++ has an issue with ambiguity.
So in this case, remember, we've got --
we're handling all of these types of initialization here,
right, 0 argument 1 argument 2 arguments and 3 arguments,
all with a single constructor.
So what happens if I decide to do something like player
no args constructor and I implement that.
Well, hopefully, you'll see the problem when the compiler sees the code on line 28,
it doesn't know what to do, it could call this default constructor
or it could call this overloaded constructor with the three default parameters.
It's not going to guess, it's just going to give you a compiler error.
So let me debug this or build it and run it you'll see the arrows.
You can see it in case, you get it you'll know what it's talking about.
It says right here error call of overloaded player is ambiguous,
which is exactly correct.