Welcome back to another lesson.
We are continuing on talking about templates, but in this lesson, we're specifically going to talk
about class templates.
And yes, you heard that right.
You can also use templating on classes, not just on member functions.
So why would we want to template a class?
Well, you might encounter a scenario where you want to make some sort of class.
And you want to, let's say, have that glass door like a container of something, or maybe it has some
data members that you define and the thing is, is that you want those data members to be able to take
multiple times, potentially without having to make a different type of code, like what if it's, you
know, we have, for example, like you see, I've declared a pear shaped list agent statelet, simplest
IACP.
So what if we have a list of shapes, but we're not really sure what type of shape it's going to be?
So what I mean by that is that maybe we want the ability to maintain a list of triangles or instead
a list of rectangles or instead a list of circles.
So of course, you could just make a vector and store that in there.
But what if we wanted to make some additional functionality that would be calculated automatically for
us?
Like, maybe this shapeless class could have a function that found the largest area of the shapes in
that list that it had.
So let's say it, the shapeless class.
It has a vector of shapes and maybe, for example, its circles.
It would find you have some function that could find the circle with the largest area out of that list
of circles.
But what if you wanted it to do the exact same thing for rectangles all of a sudden or triangles?
You'll be annoying for you to have to make like a shapeless circle class and a shape list, rectangle
class and a shapeless triangle class.
Just so you can have the same thing, we are doing polymorphisms so we might be able to just use like
the base class shape, but there's also kind of an easier and more intuitive way by using templating.
So let's go ahead and kind of show what's going on here.
So instead of me template right away, let's just make a class called shape list.
What I'm going to do is for the public, and I'll put a private section and let's say we want this vector
of shapes, right?
So I say, Vector, come here and I like Vector.
And let's say I call it a vector shape underscore shapeless like this and come back here and I'm like,
Well, what do I put for the type of the vector?
I don't want to put circle, because then it would only be able to handle circles.
I don't want to put rectangles and could only do that same for triangle, right?
And I'm not including those up here yet either.
So how would I make it be a vector that could handle any one of those things?
Or let's say that I even come up with another shape that somehow, you know, doesn't inherit from this
shape thing, too?
Maybe I come up with a class called line, and it just holds like a bunch of different lines, and it
can tell me like the distances of the lines or something.
So it's not even inheriting from shape.
So we couldn't even use like a basic shape.
Here is the type of the vector, right?
It would just be like its stand alone line class, but we still wanted it to somehow be able to have
a list of lines and consider that to be OK being in the shape list, right?
So there's a way we can do this, and it's by using template, of course.
So just like we have done with the functions, I'm going to write the word template and say Class T.
But it's going to go on top.
You notice here it's on top of the class definition.
So this will enable it so I can put that data type of T in the vector here.
And so this will make it so we can have a vector of circles or instead a vector of squares or sorry
rectangles or triangles without having to make a separate class for each one, we can reuse the same
class for different data types.
So the cool thing about being able to temper the class is it lets us have some data members here that
could potentially be different types, you know, we also might have something, let's say like, you
know, each like shapeless, like the shapeless that we have.
Let's just say like, you know, we have something called like a current shape and this type of team,
we just say like T current, let's say, current shape type or just do like underscore
something like this.
So maybe we are not sure whether it's going to be a.
Circle or a square, something we want to like, take one of the shapes, right?
So if it's a circle, we'll just take like the first circle in the vector and we'll set it to like,
you know, current shape or something.
I don't know, but I'm not going to leave this here.
But just to illustrate the fact that you could do this right, we can even have it declared as a data
type T in our private data remember section.
And just because we've put this template here.
So I'm not going to keep that there because it doesn't seem very sensible.
I'm going to have this vector of type T was the class template type so it can accept anything that comes
into it.
So what else should we put in this class?
I'm going to go ahead and put on a constructor, right?
So I should say shape list.
And then what if we have some cool methods, maybe like I say, like prints, print list or something
like that?
And this'll just like, you know, print the shape list out.
Maybe I say that like largest shape, right?
So what if I want to say?
Look, I want to say that we will return the largest shaved or something like that, so I could say
that we will do so return T and I will say like get largest shape, maybe get larger shape out of that
vector.
So it'll, you know, find whatever shape it is and return the largest, the one with the largest area.
And we'll, of course, maybe want something to add it to the list, right?
So what if I say add shape, right?
And then this will take in some type of shape.
We're going to use Ti again because we're not sure what the shape type might be.
We're just going to use our template type for that.
So let's say the parameter will be typed.
So I'm just going to say shape right here.
I'll say s.
Cool.
So this kind of gives us everything here.
And so one, before I generate these function definitions, I want to kind of point out some important
details.
So one thing that we're going to have to do if we have the template here in the header file and we have
a separate zip file is that this may seem weird, but instead of us putting like some of them in here
instead of us doing in the CBP include the shape forms and spell.
That right include shape, Lester age.
We're not going to put that in here.
Instead, we're going to do the complete reverse.
And here we are going to say
include down here and we're going to say shape list dot CVP.
And why are we going to do that?
Well, it's a problem with the templating, if we template the header file here and we decide not to
put the implementation in the same file.
Then things have to be flipped around, so the compiler will know how to generate everything correctly.
So for that reason, you have to have the definition here in the header file.
So put all your prototypes and everything in the header file here and underneath that, but before the
macro guard stuff finishes.
So, you know, you make sure to put this as well.
Put your macro guys.
But before you have this, and if and after the class definition, you should have it include and then
the CPE implementation file.
You also can just ignore, you know, totally not new separate files.
And if you wanted to, you could erase this, you know, and just take everything that you would put
in this heap and just start, you know, typing it right here, you know, paste it right.
There have all the implementation in the same file, and that's totally fine as well.
I just want to show you how you can do it both ways, you know?
So I'm going to include this checklist CBP here.
Another important thing about Sea Lion is that you're going to want to make sure that the shape lists
H and shape list copy whatever the template files are.
You know, anything that has to do with templates if they're in separate files.
Of course, you're going to want to have to go one or want to go over here to see make lists, and you're
going to want to make sure that they're not listed here in this ad executable section.
They should not be added as targets to the build process.
You know, this is what this is.
The build process like a file, one of the files that's needed to successfully compile the projects
here and you list your target files to compile, but you're not going to want to have shape list or
shape list CPP listed in here.
Otherwise, it's most likely going to throw some errors.
So I want to point that out as well.
So if you're not working on here, just make sure that you're like, if you're using some other type
of make file or something to compile, just make sure that you're including only the other files as
targets.
This will just be considered a library.
It'll work out.
Don't worry, the CP doesn't need to be compiled because this is being included here instead.
All you have to do.
I'll show you this once we get to main is just include the header and main.
And it's automatically just going to all work out, it'll go through here, it will use it as like another
library that gets imported without you having to compile it and have these files as targets so don't
don't include them as targets.
So let's go ahead and generate some ecotourism and generate a definition.
And it's not putting it in the air, so let me just generate it and copy it, so I'm going to go over
here and I'm just going to copy it here and then I'll go here and generate this definition.
All right, cool now it went ahead and put it in there.
I don't want it to include this, though, so I'm going to get rid of that once I once I do this, so
generate a function for this.
And let's go ahead and generate a function for this.
Cool.
So what I'm going to do now is go up here and definitely get rid of this because we don't want to include
that.
And so you notice that when I generated it, it put this template class T on top of the member functions.
Also notice that it went ahead and instead of just putting shape list for the scope resolution part,
you know, here's the scope resolution operator for the name of the class input shape list and T right
here.
So this is another part of the syntax.
If I click this right here, it will expose this template.
So this is another part of the syntax that's important.
So when you do this class, every function, even though you're not really thinking about them as being
templated functions, you need to have a template syntax.
And this is well on every one of the member functions here.
OK.
And that does this.
Regardless of whether you're using separate files or putting the implantation in this header file,
you're still going to need this template class T over all the functions, and you're still going to
want to put this part here for this scope resolution.
So just want to make sure that that's very clear.
All right, cool.
So you notice this stuff highlighted just because I'm already using this in Maine and I'll show you
the code that I'm using in that client file.
So let's go ahead and implement some of the logic for this stuff right here.
So I'm going to come in here for shape list what I actually want to do.
I'm going to make an initialization list for this constructor, and I'm just going to say shape list
or vector should just be a new vector of type T.
Like this?
I'll use the Vector Ops Vector Constructor, right?
So this is going to be my initialization list style constructor.
So this will make a new vector here of type T and set our data member shapeless to that.
So add shape takes shape and all we're going to do is, say, shapeless start, push back and s.
And so this is type T, right?
This is already Typekit here here.
So it's going to be able to add that, OK, cool work for any shape for this print list I'm going to
go through.
I will do kind of an item based loop here with the auto keyword.
So I'll just say auto S4 shape in shape list and then I'll go ahead and see out the let's see.
We'll do the shape list color of maybe first.
So I'll say s dot
get color and get color.
Is that what it is?
Get color.
Okay, cool.
Escort get color so this can be like blue, and then let's say like we do a little space and then we'll
say, like an escort.
Is it type?
She was going here to see that type.
Right.
So type, so this could be like, you know, like blue rectangle,
and we'll just say with area and I'll say S-type area.
And then we'll do an incline.
Cool, so I just want to print out some info about each shape, right?
So I have this kind of bass loop.
I'm using the other keyword, so it resolves to the type.
And then it goes through shapeless Australian, and so for every shape in the shape list, it's going
to say the shape, get color.
So for example, this could be blue and then a space, and that's going to say the type.
So like Blue Circle Width area, and then it'll print out the shapes area so we can print out all the
info and loop through all the list of the shapes that we have.
You get larger shape.
I think I'm going to do something like where I make some temporary variable and it's just going to come
called like the largest in index or sea index.
So how about I say largest index equals zero?
So we'll start at zero and then I'll say four and I equals zero is less than
shapeless size I have plus plus.
And then what we'll do is say if let's see.
So if shape list I.
Dot area is greater than the shape list and the largest index dot area.
So what I'm checking right here is I'm saying like it's the current shape that we're on and the list
is it's area greater if its area is greater than.
The largest one so far, right?
So I start watching this is zero, but I'll just keep updating the largest one.
So I'm saying if it's larger than the current largest, then we'll just go ahead and save it.
The largest index equals I will change the index of that right?
And then that way we can update that.
Update the index as the largest one.
Cool.
So, otherwise, it'll just keep going through, and then at the end, I'll just say return ship list
and I'll say largest, I'd say the largest index, so that would be able to get the largest shape for
us.
And I think that's kind of all I want to add right now.
Yeah.
So we will go over to Maine now, and we'll kind of test some of the stuff out.
I already have some code there.
I'm going to change a little bit because I kind of renamed this.
So let's go ahead and check this out.
So I kind of have these pointers left here, but I'm going to make some more variables that aren't pointers.
So I have like some circles and rectangles, for example.
And so let's talk about how we can now make a shape list object.
So first of all.
You're going to want to include the simplest header up here, just like any normal header, like, you
know, these ones.
And then what I'm doing is first, I'm making, like I said, some non pointer objects of rectangle
and circle.
I go here and I say shape list, and then I put the type here.
The explicit type here because shapeless expects since templated, it's kind of like a vector, right?
It expects you to put the type that you want to be associated with the class.
So this object, this shapeless object I'm calling SLC for shapeless circle is of type circle.
Yet I'm still able to use the shapeless class to create a rectangle version of it.
And I have a special object now that is shapeless rectangle.
So this area after so here's the class name, right data type name.
But also a part of that is the template.
So you put the class name, then you put the template type in the angle brackets and then you can put
the name of the variable right in the variable name.
Same thing here for rectangle, right?
So I have two different types shape list circles, shapeless rectangle, and I'm calling them appropriately.
And the way that I'm doing that is through this angle bracket template type here.
So I'm going to change this to print list instead of print shapes, assistance or other stuff earlier,
so we're going to change this to print list.
What else should we do?
Maybe we can say largest shape or something like that, so.
Maybe it will print the area of the largest ship.
So let's just say we print the list and then after this, we'll say, like SLC.
Uh, let's see.
See, see out SLC.
Dot.
Uh, get larger shape.
Dot area.
How about that?
And I will put this.
Copy paste this here and after this print list, I'll just change it to SLR so I can get the largest
of the rectangles too.
So you notice I'm also d referencing one of these pointers up here.
So this circle I just consider see one in this rectangle I was considered kind of like as if it would
be R one, but I'm using the pointers.
But what I'm doing is I'm passing them as d referenced to this shape because you know that over here
we when we add the shape, we expect it to not be a pointer just to be, you know, a normal object
of type T..
You can also do it with pointers to we could rearrange this and do it.
But just for simplicity of step, I think I'm just kind of like doing it like this.
So let's go over here.
So you notice there, I d reference that that's why this star is there.
Same for the rectangle just referencing these pointers up here so I can pass a normal object.
Let's go ahead and run this and see what we get.
OK, so pretty cool, right?
Let's go ahead.
Let me zoom in on this here.
So we get a green circle with Area 277, Blue Circle with Area 47 and Black Circle with Area 191.
We see that the biggest one was 277, so that worked out and found the correct one.
You know, the rectangle as well.
We see all these.
And it found the largest one for the rectangle as well.
So let's just compare that to what we were up here.
Seems to be pretty good, at least these are.
Correct, right, so we have a green of blue and a black green, blue, black and red and purple purple,
purple.
These are all purple.
So pretty cool.
So I didn't test it with the triangle, but it totally be fine with the triangle as well.
I used the print list, the ad shape and the get larger shape, so we tested all three of those.
And so the main takeaway is just the syntax here and the idea that you can use the template on a class
as well.
So it's definitely a powerful tool.
Templating is kind of one of the coolest things that you can do in C++, and it really makes it a kind
of competitor with some of the more modern languages that kind of have these automatic and more dynamic
systems with typing and stuff like that.
So with that, I am going to leave you with what we talked about so far in this lecture and not go any
further with this, but you should be able to look back on this and understand how to deal with the
templated classes as well.
Remember some of the important points that are kind of little important details like including the copy
in the header, rather than including the header in the CP whenever you're doing separate files for
the templates.
Also, if you're using Feli and make sure to not have those two files in the targets if you're doing
separate files and that means don't have them in this list here in the see make lists.
And if you're working in something else, just don't have them in the targets to whatever the building
process is, if you're using make and making make files.
Good for you, but just don't put those targets.
And just to let you know you can take all the CBP code and just remove this highlighted line and put
it in here and have it all in one file.
So with that, we are nearing the end of this half, first half of the course.
We've talked about almost everything there is in basic programming and syntax for C++.
I am going to have one final project for you to do.
And then after that, there will be the second half of the course, which will be all about data structures
and algorithms.
We will continue using C++ and we will be putting a lot of this stuff to use.
In fact, we will be using templating for the first data structures that we go over.
We will need to use templates to deal with those.
We're going to use that just so we can practice as well.
So you feel comfortable, more comfortable with templates as we move on.
We won't be using templates all the time, but we will try and get some practice.
So you feel comfortable.
OK.
So with that, I will see you in the next lecture.