>> Well, so what I want to
do now is illustrate how to get started on an assignment. The assignment we're going to
look at is your assignment 3, Homework 3, the product class. So this is the document
for that assignment. Let's just review briefly
what's expected. First of all you're expected to
know some stuff, the first chapter on classes, the second chapter on
classes, the chapter on pointers and the chapter on string
objects are relevant to this. I think Chapter 7 on string objects is
less relevant, but there's a little bit of stuff in there on C
strings that might be helpful. Definitely look at classes Parts I
and II and be familiar with pointers and C strings to get this done. You typically begin by checking
out some distributive stuff, there's a submit script, there's some
executables that are distributed for you to look at and some tests, software
for your code that's distributed. So, I believe there's a meg
file in there somewhere too. I distributed a meg file
I'm pretty sure. If I didn't, then I'll
set to turn one in. There's one in the distribution as well and so you can use that
one if you want to. So our basic problem is to
look at the deliverables, which are product dot
h and product dot cpp. Product is supposed to be a class and this diagram tells us the
specifications for that class. This is typical of the kind of class,
a specification diagram, you would see. First of all the class has a name and that's important for
everyone to agree on. Services for a class in practice
turn out to mean the member functions and member operators of the class. So the services that class provides
right now are set name, set bar code, set cost and getters for each of those,
get name, get bar code and get cost. The bar code set takes a C
string, it's a const pointer, which will not allow you to modify
what that pointer points to. The bar code is a 32
bit unsigned integer, the cost is a floating point
number and those same kinds of things will be returned
by the getters. The properties that's supposed to
be constructible so you're supposed to be able to make objects,
create objects, that tells you you need constructors
and copy constructors and, you need constructors and
destructors and assignment operator and passable is going
to mean that you need to have a copy constructor
on there as well. Come on in. We're getting a start on Homework 3. So, the private variables for this class
are going to a C string called name, a 32 bit unsigned integer called code
and a floating point called cost. So how do we get started
on something like this? Well, I just pulled in, I'm going
to login to lin prog [phonetic] and that's what I just
pulled up on my screen here. So I'm going to go into 3330 slash HW3. Of course, I've already done this. I need to be a little careful. So I'm going to call the, instead of
product dot h and product dot cpp, I'm going to call it
p dot h and p dot cpp so I can be starting
out on an empty file. So, product dot h works. There's nothing in there right now. So, the first thing I do
is put in the easy stuff. It makes me feel good to
get a few things in my files that don't take a lot of thinking. So, this is the file that would be
called P-R-O-D-U-C-T dot H and also that file will be me and the creation
date of that file would be today, which is the 24th of September. I'll come back later and add more but that's the absolute minimum you
should have in your file header. You may as well put it
in there from the get go. So now I know my task
is to define a class and that class is going
to have a name, product. Now, I usually put my opening
brace and my closing brace and my required semicolon in
now so I won't forget later. I'm going to have some public
and some private sector. So in my public sector, I might
start out by putting in my services. I'm just going to click on this to
remind myself what the services are and the person that made this class
diagram very conveniently actually put the correct syntax for the
function prototypes in there. So I'm going to just save myself some
typing since I'm a poor typist and copy and paste those babies right in there. So, let's see my emax should be
formatting this correctly for me. Oh, the emax is slightly
confused here because whoever made that didn't actually put the
semicolons in for the prototype. So I need to put those in. [ Pause ] I'm going to fix this a little bit. I'm just kind of cleaning up the
way the file looks here and now that should all be good and you'll
notice emax is now formatted correctly and put the right number of
spaces in for the lead and so on. So those are my, that's my
functionality of the services. I know, however, that I'm also going to
need some constructors and destructors. So, I'm going to put a
constructor, a default constructor and a copy constructor or destructor
and assignment operator in here now because I know I'm going to
have to do it eventually. So, the constructor, the default
constructor would look like this, the name of the class and no arguments. The destructor would look like tilde
the name of the class and no arguments. The copy constructor always
looks like the name of the class and incoming object of that
type with constant reference. So I'll do const product
and I'll give it a name. You don't have to name that
argument here but I'll put it in there; it's okay to do that. So there's my copy constructor and
now my assignment operator is going to return a product by reference. [ Pause ] The name of the assignment
operator is operator equals mark and its incoming argument would be
the same as the incoming argument for the copy constructor
so I'll just reuse that and there's my assignment operator. Now I think that I'm supposed to
have another constructor somewhere. Let's just read more about
the specifications here. The class should be a proper type to
include a default argument constructor that initializes the data fields. The default constructor should set
the name to sharp and a bar code. So I need to make a comment to note to
self here that this should have name, sharp and cost of bar code
0 and probably cost 0. I can't remember if that was
stated or not but just assume that, but there's another constructor that's
supposed to have 3 arguments and it, the arguments would be the name,
product name, product code and cost. I've named the variables,
I've given their types and their names in that as well. Again, you don't have to
actually name the variables, but I went ahead and did it. Let's see here. Maybe I can save some typing by copying
private variables with the mouse. [ Pause ] So, the viewing I believe that
we have now defined the class. That little ding was emax telling me
I didn't end my file with a new line. There was something about
output operator as well. Is there not? Yes. We need the output operator. Now I have a little advantage over most of you I actually remember
what the prototype of the output operator should be. It should be reference to
an O stream and, you know, I should follow my own
rule and put S-T-D so that's the return
track of the output. It's name is that, operator
less than, less than. This is just an overload
of the left shift operator. You've probably learned that by now
by looking at the bit vector chapter. So anyway that's the name of the
operator and it takes 2 arguments. The first one is a standard
O stream object by reference but not const reference. I'm going to go ahead
and give it a name, OS, and right here is the second
argument for the output operator is where you put the type but
you're overloading this thing for and the type we're overloading
it for, of course, is product. We could choose a past product
value, but it makes more sense to pass the reference just because it's
inefficient to copy these products. It takes a lot of space and it's
better to pass a permission slip that says send my product
information out to stream and so that's the way we'll do it
and put cost on there that says by the way you can send my product
out to stream but you can't modify it. While I'm at it, I'm going to go
ahead and put the if and def stuff. This protects against
multiple read of a header file. So, it's a compiler. If and def means if the filing is not
defined and the filing is going to be, my file name, I'm going to call it
underscore product underscore h. So if that's not defined,
we're going to define it. [ Pause ] Then the end of that if
statement is down below. Just so you'll understand what's going on here let's say this symbol
product underscore h is not defined and define it and go
ahead and read product. The next time in the same compilation
if this were to get read, that if, that h if not defined would
be false because it is defined because it just got read and
defined, and that would then skip over the definition and the
reading of the class definition. So, that has the effect of
allowing this class definition to be read only one time, which is
important because C++ will get confused if you try to define the same
thing twice as you might expect. It's got no way to know it's
really the same definition. So the rule is it won't allow you to define the same thing
two times and compilation. So that's what protects
you from that problem. All right. So, what I think is I've
got the class defined. There's always a possibility that
I've got to come back and tweak this, but for now I've got my 3 setters
that were required, I got my 3 getters that were required, I got default
contract or 3 argument constructor, a destructor, copying constructor
and assignment operator. They are my private variables. Finally, I've got output operator. [ Pause ] So I'm going to save that. Now, comes the implementation part. Let's just talk briefly
about the implementation. Notice in the private sector
we've got 3 variables. We've got const char, which is a C
string, that's the one that's going to consume most of our
effort and tension. We have 2 other variables. One is an ordinary integer,
32-bit integer called code and one is an ordinary
number called cost and those will be more easily
handled than the C string. The C string is going to give
us a little bit of trouble because a C string requires
a dynamic memory allocation. So any time you get into that you're
allocating resources to a class and they have to be taken into
account by the constructors and the destructor including the copying
constructor and the assignment operator. We also have this thing called set
name, which is going to have to take into account dynamic allocation as well. So, with that I'm going to move on to
the implementation file for the class. So I'm going to do Control W write file. I'm going to write this same file to t
dot cpp and so this is now an exact copy of the header file and I'm
going to change my file name. In the code file, I don't
need protection. I'm going to comment out
the class for the moment. [ Pause ] Get rid of this in def here. So I want to leave the class there,
you know, as it appears in the file and first thing I need to realize is
I need to include the header file. If you recall, I really named that
file t dot a. So I'm going to cheat and call it t dot h here even though
you're supposed to have product not h, but I've already got
a product h in there. I want to do this again. So p dot h. That reminds me I'm
going to read that p dot h back in. One thing I know because I mentioned std
O stream here, the first thing I'm going to have is a complier complaint
about what the heck is an O stream? So, I'm going to put and
include a statement for, see, I told you I was a terrible typist. So I'm going include io
stream and that'll guarantee that there's a definition
for std o stream and I won't go to compiler from that. I think I'm going to also need
to include C standard integer, which is where u int 32 is defined and almost always need
the C standard library. [ Pause ] And I might as well, okay, I'm
pretty sure that's good enough for the header file. I'm going to go back
now to the code file. I've included tia so anything I included
in the header file gets included by that statement, but
I think I'm also going to need the C string library
in my implementation file. I know I'm going to because I've got
to be messing around with C strings. So that's, that I don't really need in
the header file to declare the class but I do need it in the
implementation fire to actually implement the
class member functions. So, this is all now, what I'm going now
is just fixing up doing some housework to kind of get these prototypes
converted into function headers. So, they're all going
to have to be product. So I'm going to put that
in for each of these. [ Pause ] Whoops. Didn't mean to do that. [ Pause ] And I'm not going to need the
documentation anymore here, I don't need the semicolons anymore. [ Pause ] So now I'm going to, the
h will have a [inaudible]. I'll put those in. I didn't get around to the
constructors and destructors yet. So let me hit my tabs on the emax now. Okay, so there are headers
if you like for, I'll get rid of some
of the specs for space. [ Pause ] So I can go in and just
start filling in these braces for the various setters and getters. I'm going to start with
an easy one, set bar code. I thought I put a name for that in
there, but I guess I don't need it. So I'm going to call it code and leave
it here, of course while I'm at it. Cost. So let's see and set name. So let's say set the code equal to the
incoming thing called code I just need to do code underscore and that's
the class variable equals code, code without the underscore
is the function argument. Code with the underscore
is class variable. So that sets the class variable
to be the value that was passed in to the set bar code function. Set cost will work exactly the same way. Cost underscore, which is the name of
the class variable will be the same as the cost being passed
in as an argument. Get name I can just return
name underscore and it will be returned
as an const order. So even though I'm returning a pointer
or two that I own as an object, it's being passed with const
requirements that will not allow anyone who uses it to change my data. So that's safe. Get bar code return code that's
returning my data, that's safe. Get price is returned price again
returning my data and that's safe. So, the only one that I haven't
tackled yet is the set name. That's the one I have to come to
grips with dynamic allocation. So let's just review up here
I've got a copy of the class. We call that the name is a C
string so that means it's a pointer to a character array and character array
that has got one element for each letter in the name plus one extra slot where
we store the null character at the end and that's what makes it a C string. So, we can assume that the
const [inaudible] are coming in on set name is I'm giving
incoming variable in name here, a name without an underscore. We can assume that it's
a well-defined C string. If the client doesn't give
us a well-defined C string, we can't be responsible
for making everything work. So that's the client's responsibility,
but it's our responsibility to rename our product object
with that name right there. So there's two problems to worry about. First problem is my product may
already have a name and, therefore, I am actually changing a name or my
product might not yet have a name. So I've got to worry about that first. So, I can say if, and remember the name
of our C string is name underscore. That is a pointer. If a pointer is 0 or null, you may
use the, you can us N-U-L-L there if you prefer, then that means
the product doesn't have a name. Actually I want to say if it does have
a name, then I want to get rid of it. I'm going to delete an array of
characters so I have to use delete with the 2 square brackets. That version of delete. Okay, at that point name
underscore is the null pointer. If it wasn't null to begin
with, I've just made it null and legally given back the memory that
had been previously allocated to it. So now I can start fresh and build
up name underscore a copy of name; a separate copy of that string. It's complicated because I first
need to know how much memory to allocate to receive that copy. I, therefore, will store that value. I'm going to call it size and now the
first of two functions we will use out of the C string library. S-T-R-L-E-N. That stands for string length. I want the length of name,
the incoming C string. Now, how many characters
do I need to allocate? >> One plus that. >> One plus that. So I'm going to make my name pointer
on one plus size worth of characters and right after that because I'm
very forgetful, if I don't do it now, I will forget, I'm going to
null terminate the string. So the size plus first character
in that string is the last one and its index is actually size. I want it to be the null character. That is the back slash 0 character. Of course you put it in single quotes. Okay, now I have allocated
space and null terminated so it'll be a legitimate C string. So now I need to copy the data from
name into name underscore and that's where I make my second call to a very
helpful function of the C string library and that is the S-T-R-C-P-Y
function and it goes right to left kind of like assignment. So the receiving string
goes left parameter and the string we're
copying goes as the right. [ Pause ] So let's just review this. First, we've got to make sure that name
doesn't have anything allocated to it. So we check to see if it does. If it does, we delete it. By the way it's an error to
call delete on a null pointer. So you do need to make that check. We see how big the name is on
the parameter being passed in. Allocate 1 plus that amount of character
space in an array called get address and let name underscore
store that address. Null terminate that block of
memory and finally copy name into it character by character. So, that is really how, that is
kind of a lesson in how to deal with dynamically allocated
resources for objects, for classes with allocated resources. So let's go down here and fix up
our prototypes for the constructors. Two constructors, a destructor and
copy constructor and the operator. [ Pause ] I'm just hitting tab here
to get everything formatted. So now what I've done is convert
what was prototypes inside the class to function headers with
empty bodies outside the class but with the class name
space resolution. Now I'm ready to start
doing these things. Where do we start? Well, one place to start
might be the destructor. The destructor has to get rid of
any dynamically allocated resources, which may or may not be
the name of the product. So the destructor would do something like if it has a non-name,
then delete it. [ Pause ] Let's see the, I believe the rule said
the default constructor is supposed to give it the name consisting of a
single character char, is that right? Yes. So, by the way you should try
to initialize your class variables in the same order that they
are listed in the class. The first one, and you should also try to initialize them in
initialization list. So the first one is name underscore
that's a pointer so we're going to initialize it to have
the value 0 or null. You never want a pointer to be
uninitialized if you can help it. I guess the next one was the code. C-O-D-E. We said that
the, well, we can put 0. The code will be 0 by default
and the price will be 0. I'll say 0.0 to remind me it's a float. Yes, sir? >> Is it price or cost? >> It's probably cost. Thank you. Now, that was a good question. Note that I haven't finished with name. Code has now got the value of 0
and cost has got the value of 0.0. Name hasn't been fixed yet. I just made it the null pointer but the
specs say it should be the name sharp. So, I have to do an allocation, how
many characters are allocated here? >> Two. >> Two. Very good. One for the sharp character
and one of the null character. So I'll put name. Okay. Now what about this constructor? It would look similar to this one. Similar to the default
constructor initialization list. So, what name, null,
that's a good start on name. O instead of 0 we can make it the
incoming argument and cost instead of being 0 we can make it
be the incoming argument. So, again, we've taken care of the 2
ordinary variables that are numbers and we have to now go through the whole
deal with this string much like we did with the set except we don't
have to worry about whether or not name is null, it is null. So you do foresee it as set name. Of course, using, the incoming
thing called name for the name. What about the [inaudible] constructor? Well, again, you always use an
initialization list for any constructor. So, what is the, so we initialize the
pointer name and we can't really do much with a pointer except make it null. Then we can do the code and now
the code you want to be the same as the code in that product. So, that could be the dot notation
and the cost you want to be the same as the cost in p. Okay, so in
the int list I've taken care of again the 2 ordinary variables but
I have to worry about the name thing. So, again, you proceed. [ Pause ] Except you don't worry about delete. I hope that makes sense. I could have said the
same thing up here. I could spell worry correctly
too while I'm at it. Finally you have the assignment operator and the assignment operator is still
quite similar to all these others, but there's assignment operator
overlay that you have is, you have to worry about self assignment. So you do first protect against self
assignment and I usually, again, I usually try to get that out of the
way first and this is the address of me, my object, and you want to make sure
that's not the same address as p but p and this are the same object. The assignment has nothing to
do other than return reference. So, outside of this the very
last line is return star this. That looks like it returns the
object by value but because in the way the prototype is
it's actually returning it, a reference to itself. Now what you've got to do is fill inside
of this if statement and what goes in there is very similar to set name
including the part about the deleting. So this is exactly. [ Pause ] And that's pretty close to it. You've got to do your
operator, your global operator so that output operator
as well so remember std. [ Pause ] Give that name os and I think
I'm doing this all in prototype and this here I have product p and I
guess I'll pass it by const reference. [ Pause ] And I think I'll check the specs. I don't remember exactly
what it said about that. Display the 3 fields
with a tag character between them and don't put any new. So, you run those through that
stream called os right there. So we do os. It would be tempting to
write p dot name there. Why is that not going to work? [ Pause ] It's not going to work because
name is a private member and this operator is not
a member of the class. Op and operator cannot be a member of
a class and we didn't say it was going to be a friend of that class either. It's generally something you
want to avoid if you can. So, that's not going to work but fortunately we do have a
public service called get name, which could serve the same purpose. So we'll say get name is a const method and so it won't dilate the const
restriction be placed right here. Now we can put a tab. [ Pause ] And we now put, by the way the emax
noticed my little output thing there. I like to line these
babies up like that. So everything is readable. So what's the next thing we want to output would be the
bar code another tab. [ Pause ] Something is going on here. I must have hit a Windows key somewhere. Also I forgot my little second
quote thing didn't show up here. Why is that not? Now, I'll do p dot. What's the last thing, get cost? That's it. No new lines, right? Just output the name, tab,
bar code, tab and cost stop. It's what I'm asked to
do with the specs. So that should work for
the output operator. All 3 of those are const
member functions and so they're not violating
the const restriction, they're public so I don't
friendship or anything. That should be okay. So, really I can kind of just make
a copy of the code and set name and plunk it in right here. I'll need to change a little
bit because I'm dealing with p dot name instead of name. I'm dealing with p dot name underscore
and so incoming name argument, but other than that it should be the
same and here I'm dealing with name and argument as we did in set name. So, it should be okay. Some people will ask, well, couldn't
I just call set name in both of those? I'd rather you not do that. The problem is one of
chicken and the egg. So let's say I copy, let's say in the copy constructor you're
making a copy of an object. That copy hasn't been made yet
completely and yet you're going to call a member function
of that object. It's not logical to call a member
function before object exists. And so compilers will normally
rescue you from that little dilemma, but I just think it's better not
to put that burden on the compiler; just go ahead and write the code
for it and not call a function, not call a method of an object before
the object is completely in existence. So it's a little, in other words, that would go for any
object that's being created. So any one of your constructors and the assignment operator
it's a little bit illogical to call a member function in the body of
1 of those 2, one of those [inaudible]. Any other member function implementation
you can call another member function no problem. It's just slightly logically
problematic to do it in a constructor. Any more questions? I'm going to leave that.