In this video, we'll learn the c++ syntax for deriving classes from
existing classes using inheritance.
First, we start with the class declaration for the base class.
This is the class that we'll be creating the new class from.
This class will have its own member data and methods as we've
already learned in this course.
Then we declare the new class derived in this case, followed by
a colon then an access specifier and the name of the base class.
The access specifier can be public, private or protected.
If you don't provide an access specifier, private
inheritance is used.
Let's see what the access specifiers do.
C++ allows for three types of inheritance: public,
private and protected.
This is very different from many other object-oriented programming languages.
Most other object-oriented programming languages only
support public inheritance.
Public inheritance is the most common form of inheritance, and
it's the type of inheritance that we'll most often see used in c++.
Public inheritance establishes an "is a" relationship between
derived and based classes, and it's the type of inheritance
we'll focus on in this course.
Private and protected inheritance establish a derived class has
a base class relationship.
It is often used to implement one class in terms of another.
Private and protected inheritance are beyond the scope of this course.
Let's see an example of deriving a savings account class from an account
class using public inheritance.
Notice that we're assuming that we already have an existing account class
and it's got its own member data and methods, and we want to reuse it.
Now suppose we want to create a savings account class that
has much in common with an account class, but it also has
some more specialized behavior.
We can declare the savings account class, then provide a colon followed
by the public access specifier, and finally, the name of the base class.
This establishes an "is a" relationship between savings account and account.
Now a savings account inherits everything in the account class,
and it's free to implement its own specialized behaviors based on the
behaviors it inherited from account.
Of course, we now have two classes in our application, so we can create
account objects as in this slide.
We assume that we have a no args constructor in the deposit and
withdraw methods handle deposit and withdraw funds to an account.
We can create account objects on the stack or on the heap via pointer
and call these methods as we need.
We also have a savings account class, so we can create
savings account objects.
In this case, the specialized deposit and withdraw methods of the
savings account class will be used.
So as you can see, conceptually inheritance is pretty simple.
However, the nuances of inheritance can get very complex.
Let's head over to the IDE and create account and savings account
classes, and then we'll learn about protected member access
specifiers in the next video.
Okay, so I'm in the CodeLite IDE.
I'm in the section 15 workspace in the DerivingOurFirstClass project.
And what I've done is I've created a real simple account hierarchy with two
classes, and it really does nothing.
It just has a couple of deposit withdraw methods that just say, hi
I'm deposit, hi I'm withdraw, just so we can see them being called.
And then what we'll do is we'll tweak this just a little bit so that we can
add some attributes so you can really understand what's going on here.
So let's take a look at the account class first.
This is our base class.
Notice that there's nothing going on here.
Everything's public.
We'll worry about protected and private in the next couple of videos.
But right, now all we've got is a deposit method, a withdraw method, no
args constructor and a destructor.
Okay, so let's take a look at the implementation.
And as you can see, the constructors and the destructors
are just there with no code.
Our deposit method just simply says account deposit called with
whatever amount we called it with.
And the withdraw method says account withdraw called with that same amount.
So can't get any easier than this.
So now what we're going to do is we're going to derive a
savings account from an account.
So what we'll do is we'll create a savings account header as
well as implementation files.
And you'll notice right here in savings account, we're
including account.h, right.
We've got to include that header file.
Otherwise, this class of the compiler won't know what an account is.
And here's the syntax class Savings Account. That's the
class we're deriving and then public account account in
this case is the base class.
And you can see that this class is also really simple.
It's got a no args constructor,
it's got a destructor,
and it's got its own version of deposit and its
own version of withdrawal.
And the implementation.
Again, the constructor and the destructor don't
have any code in the body.
The deposit simply says savings account deposit called with amount
that way we tell the difference between when the account deposit
method is called and the savings account deposit method is called
and the same for withdrawal.
Okay, good, so now let's take a look at our main.
It's just a real simple main that exercises some of these classes.
So what we'll do here is we'll create an account
object right here named acc.
And again, this is an account.
This is our base class.
This is not using inheritance right here, right.
This is just instantiating a base account.
And then I'm going to call deposit and withdraw.
What we expect there is for the deposit and withdraw methods of
the account class to be called.
And we'll do the same thing here with a pointer, just so you
can see that it works exactly the same way with the pointer.
Then what we'll do is we'll do the same but with a savings account.
So we'll create this object right here savings account, and it will
be a savings account, and we'll call the deposit and the withdraw
methods for the savings account.
And what we expect there is to see the output saying savings account
deposit, savings account withdrawal.
Okay, and again, we're doing down here with the pointer.
So I'm going to build and run this, and we'll take a look at the output.
And then what we'll do is we'll modify these files just a little bit
so that you can really understand what's going on behind the scenes.
Okay, so there's my output.
And I'm going to move this just next to the main so we can
see exactly what's going on.
Here we go.
So we're creating this acc object, and we're calling
deposit and withdraw on it.
And you can see right here we're calling the account deposit and
the account withdraw, that's exactly what we expect because
acc is an account object.
In this case, there is no inheritance going on.
I'm simply using a base class as I've used all along.
And down here, you can see these last two statements right there for the
account is just using the pointer.
Okay, so now let's take a look at the savings account.
So here's the savings account right here, and I'm creating a
save account object right here and then I'm saying saving account
.deposit saving account.withdraw.
So in this case, I expect the savings account versions of
those methods to be called.
You can see that that's exactly what's happening here.
Okay, so again, the account is the more general class
the savings account is a more specialized class.
And since we've got those methods that we've specialized in the savings
account class, those are the ones that are being called right here.
Okay, so hopefully, that's clear.
Now let me make a couple of small changes, and then we'll run this
through the debugger, so you can see the structure of these classes.
So let's go into the account class.
And what we can do here -- and again, I'm going to keep
everything public for now.
We'll change that in the next videos.
What I'm going to do here is I'm simply going to create a double
balance and a string name just for a real simple name for an account,
and let me include the string header.
Okay, so now we're saying that all accounts have a balance
and all accounts have a name.
We obviously, need to initialize those.
I'm just going to initialize balance to 0 and name to
something like an account.
So we can do that in our implementation file right here.
We can do it right here in the no args constructor.
We can simply say balance is 0
and name is an account or something, anything really.
Okay, so that's it.
So now we'll go into our savings account, and we'll say okay, a
savings account will also provides its own version of functionality.
Remember, this is the specialized class.
So let's say that a savings account has an interest
rate, and it's a double.
So obviously, we'll initialize that as well.
We don't want it to have garbage data.
So we're going to come into our implementation file, and we'll do that
right here using an initializer list.
We'll say interest rate, and, I don't know, let's say it's 3% interest.
Okay, perfect.
Now if we run this we should get exactly the same output
because nothing is being changed.
Output statements really aren't displaying interest
rate or name or anything else.
So let's just be sure that it runs.
There's our build there's our run.
And again, nothing here has changed.
But let's take a look at this in the debugger.
So let me close this up real quick and I'm going to go back to my main.
And what I want to do is i just want to put a couple of break points here.
We'll put a break point right here on line 14 where we're actually
creating that account object.
We'll put another break point right here on line 29 where we're
creating the savings account object.
Okay, and what I want to do is debug this, and I'll start it
and I'm really not interested in the output.
What I'm interested in here is the local variable.
So that's really what we're going to concentrate on.
So here on line 14, I'm just about ready to execute that line
and that's going to instantiate or create that account object.
So I'm going go next.
Now it's created.
Let's take a look at it.
There's acc.
It was just created. You can see the balance is 0,
and the name is an account.
Remember, the name is a c++ string.
Perfect, now I'm going to come down here to line 29, I'll just keep
hitting next until i get to it.
And what's going to happen when I get here is I'm going to create a
savings account object right here.
So I'm going to press next.
Now that savings account object has been created.
It's called save underscore account.
I'll refresh this, and let's take a look at it.
Remember, what account was, 0, "An Account".
Now let's look at savings account.
Notice that savings account has an interest rate, right.
That's what it brought to the table.
But it's also an account because we've got inheritance.
So everything that was in my parent is in me.
So there's the account part of me, me being a savings account.
And you can see that the account part of me is 0 and the account
name part of me is "an account".
Okay, so hopefully, you get some insight into what's
really going on here.
We really are inheriting all that information from our parent.
So let me just draw this out so to be really clear.
Suppose that this is acc right here.
That's acc.
That's that object right up here, and it's an account, and it has two local
variables, right, balance and name.
And we're not going to worry about what they're set to. You
can kind of see that over here.
And it also has access to those two methods right,
deposit and withdraw
as well as the constructors and the destructor but I'm not worried about those right now.
I'm just really concentrating on these two methods.
So the account knows about its methods.
Now down here, I've got a savings account.
So let me create that and I'll just draw a big box and
this is a savings account.
That's the name of the object, and its type is savings account.
That's this guy, right there.
Now savings account, remember, is an account.
So it's got an account part inside it, and that account part is going to
look just like this guy right here.
It's going to have a balance, right.
It's going to have a name.
It's going to have access to those deposit and withdraw methods.
I'll just write them here and those are the deposit and withdraw
methods for the account class.
But then our savings account - our savings account class
adds an interest rate
and it's got its own versions of deposit and withdraw.
Okay, so conceptually, this is really what's going on.
And you can obviously see it right here.
You can see that it's got the account part of it right there.
Now obviously the methods aren't here, and the methods aren't going
to be copied in every single object.
They're going to be in in one place, but think of it conceptually this way
and I think you'll be good to go because this is really what's
happening behind the scenes.
So when we say that a savings account is an account, it sure is, right.
There's the account part of me.
Now a couple of things.
We need to talk about what in here, what in here is accessible
to the savings account?
How do we initialize the account part of us?
So this is where we're headed with the next few lectures because we really
need to be able to know you know what can I access from these methods.
Am I able to access these guys right here or not?
I'm not sure, right.
It all depends on our access modifiers.
And also I need to be able to instantiate or initialize
that account part of me.
Okay, so that's what we'll do next.