>> Okay. So this is our first attempt
to make a recording in COP3330. I'm Chris Lauper [phonetic],
your instructor. This is for the benefit
of the webcam folks. And what we're going to talk about
today is introduction to classes and the assignment that's associated
with your introduction to classes. We're also going to talk about dynamic
allocation of memory; pointers; and C strings, which are in
essence dynamically allocated character overlays. So all of those things we're
going to talk about today. I'm going to try to break it up
into maybe three video sessions. The first one will be the chapter
introducing you to classes. And I'm going to go straight
to the web for that. [ Silence ] So that would be the table of contents
for Chapter 4 of the lecture notes. And the first slide is
Program Modularity. Let me just remind you that our - that
modularity is the most fundamental and significant concept
in software engineering. Modularity occurs in C plus plus
lab classes by the use of functions, what logic, we talked
about that last time. Functions provide a way to break
up programs into components. That's what modularity means. Classes provide a different way of
breaking up a program into components. And classes is what we're
going to talk about today. And classes are the fundamental
concept which ultimately lead us down to object-oriented programming. [ Silence ] So classes in C plus plus
are used to encapsulate data. So data is kept in a sort of house,
if you like, protected from tampering. So if you have data that you only
want to be allowed to be modified in certain ways, you can
do that with a class. You might want to limit
the scope of functionality. So for example, you might have
a function that only make sense when operating on the data of a certain
class; so you would want that function to be associated with the
class and not be out there in the global availability space. So you can specialize functionality to
data or you can - classes can be created by you, our clients in other
words, or classes also exist in your C plus plus library. Examples of classes that
you have in your library that you use are C in and C out. And there will be a lot more. So classes and objects. A class is a user-defined type. This is Strustrips [phonetic]
definition of a class. An object is an instance of that type. So if int were a class, then
3 would be an instance of int. So to use an object, you first define
the class, which means to define a type. And then you implement the
member functions of that class. Once that is done, you can
create an object of that type. So I'm going to give you an example. And this example is the class "date." Sorry. I stepped up to
the wrong computer. The class "date" here. And notice that class - notice
the structure of this class. It has a name, d-a-t-e. The key word "class" is part
of the C plus plus language. And there's a required
brace, opening brace. And you have the word
"public" with a colon. Then what you have is a
list of function prototypes. If you think about - look at all
those things and think about them. Those are function prototypes. One's called "Init." One's called "Addyear." One's called "Addmonth." One's called "Addday." Then we have the private
key word with a colon. And inside of "private," we
have some variables declared. All of them are of type Int. One is called "day." One is called "month." And one is called "year." Now, notice that I am following those with the ethos class
variables, with an underscore. That's not required as part of
the language, but that is part of the way we are writing our code. So when you see a variable with
an - a trailing underscore, you will know that that's a
class variable of some sort. Also, notice that our functions
begin with capital letters. And our variables begin
with lowercase letters. And our class names begin
with capital letters. Our object names will begin
with lowercase letters. Again, so that when you see those words,
you'll know immediately by the fact that it's capital or - capitalized or
not, whether it's a class or an object. [ Silence ] So let's go back and look at
these required components. They are now illustrated in red. So there's the key word "class." And then the name of
the class is "date." Then there's the required
open brace and the public. And then we have some
function prototypes. And there's the private. We have some variables. And then the closing brace. And something I didn't
point out before is after the closing brace,
you have a semicolon. And there is an explanation for why
that semicolon is - needs to be there. I'd like to point out that
if you forget the semicolon, then a compiler will be looking for it. And so there'll be a large gap of
understanding with the compiler after that closing brace where
you think you're writing code after the class is finished defining;
but the compiler is trying to make sense of that as part of that class that goes
between the brace and the semicolon. So we - that's a source
of compiler error messages that can be quite difficult
to understand if you forget to put that semicolon. Let me make another comment. I have shown you that we -- in
the public sector of this class, we're putting function prototypes. And in the private sector of the
class, we're putting variables or if you like, data - data objects. This is not a requirement. You can have functions
in the private sector, and you can have data
in the public sector. So this - what I'm showing you here
is a typical use case for classes. But it's not a - not something
that's required by the way. [ Silence ] Classes are allowed to have friends. And what friends are are
functions or operators -- which of course, are just
special cases of functions - that are in the global
name space but are allowed to access private member
data of that class. So private - stuff under the
"private" label can be accessed by friend functions or operators but not by ordinary public operators
and functions. Let me go back to just
discuss that a bit more. So public - things you put in the public
sector are available to the public through the object interface. And we'll talk more about how
you actually get to that stuff. Certain things that are in the private
sector are inaccessible to the public. So we tend to use client
server terminology. So a client of a class is
some program or another that is using objects of that type. So a client of data would
be using - I'm sorry. A client of "date" would
be using date objects. And those - that client and
those date objects owned by that client could not access
anything in the private sector. They can only access
things in the public sector. So in our definition here, the
public can only access the functions, not the private data. And that kind of explains why it's
fairly typical to put functions in the public sector and data in the
private sector so that a designer of the class is in control of how
that data is allowed to be modified. So you'll notice that we have
an "Addyear," "Addmonth," "Addday" which you can take to mean
I'd like to add three to the year. So you put a 3 in there for
int n. And you'd be able to move the year of that data up by 3. But you would have to do it
using the Addyear Function. You would not be allowed to do it by
just saying "year equals year plus 3." That would be disallowed
because year here is in the private sector of the class. So the functions are giving you a
way of controlling how a year and day and month are allowed to be changed. [ Silence ] All right. I clicked the wrong side of my mouse. So here's how you - remember I said you
got to implement the member function? Here's the way you implement
a member function. Notice that what I have here looks
like the implementation of a function. The difference that you notice though
is that the date, the name of the class, followed by the scope resolution
operator double colon is there before the Init Method is named. And what that tells the compiler is
that this is a function called "Init" that belongs to the date class. So if I left that off, it
would be making that function in the global name space and then it
wouldn't be able to make sense out of it because day trailing underscore
month trailing underscore and year trailing underscore would not
be variables known to that function. But because we're inside of the class
date, notice that we have access in this implementation
to the class variables. So we didn't have to
declare a day, month, or year with the trailing underscore. They're already assumed to
be variables in the object. And Init, I could have
called it "set" if you like. But Init can take an integer called
"day" and an integer called "month" and an integer called "year" and it will
set the date according to those numbers. And the way that is implemented,
it's just a simple assignment. Day on the right with no trailing
underscore is the variable that's passed in. It's convenient to call it
something similar just for - make the code easy to understand. But you could call it anything. You could call it "d." And whatever is passed in there
is going to is going to get copied into the day underscore, which is the
class variable with that similar name. [ Silence ] And similarly, month gets
copied into month underscore. And year gets copied
into year underscore. Here's another example, the Addyear. We give it an Init n;
and that n gets added to whatever the current
value of year underscore is. [ Silence ] So here is an example of how
we declare and use objects. And now we've - we didn't talk about all
of the functions in the "date" class; but I gave you examples of how
those would be implemented. And so now we've defined
the "date" class with class date and then an open brace. Public sector. Private sector. Close brace. Semicolon. And now we're going to - and then
we implemented the functions. So after doing that it - we can say
that we now know what a data object is and what its functionality is. And so we can declare a date object. Now, most of this is not
relevant to the task at hand. But that is how you would
create two date objects. And it's - it's - right. It's kind of ridiculously
simple in the sense that it's just as if it were two ints. Int x1 x2 would declare two ints. Right? Date, d1 d2 declares
two date objects. So it's just that simple. You have created the user defined
type date with a capital D. And we can now declare
variables of that type. Or since we know date of the class, we
can call them "objects" if we want to. But they are basically
variables of type date. [ Silence ] Some of this other stuff you
may find interesting just because it's a little bit of
a glimpse into the future. This is how you would declare a stream
object that's capable of opening - opening and reading from files. And the second - the line below that is how you would declare a stream
object that's capable of writing - opening an writing to files. We get to do it - we'll get to do
stuff like that later on this semester. A class has come with this notion of
constructors, which I'd like to mention. So if we have a class called
date, the question is how to - if you declare an object of type date,
how does that object get initialized. And the purpose of constructors
in a class is to provide a systematic way
for initializing objects. And objects, as you might
imagine, can get complicated. And so it's very, very convenient
for the programming system, the client system, for you,
the designer of the class, to specify exactly how
objects can be initialized. So what we see here is a function,
public sector function called "date." And notice that that is exactly
the same as the name of the class. Another thing to note is that
there's no return type mentioned. Not - I'm not saying void return type. I'm saying there is no return type. When you see that, the name of the class
as a function, that is a constructor. Everything that's got the
same name as the class and is a function is
a class constructor. And they come in a variety of types. What you see here is one with no
arguments and one with three arguments, a day and a month and a year argument. Remember that in C plus plus,
a function can be overloaded. So the date, which is a function,
the date constructor can have more than one form as long as they're
distinguished by their parameter lists. So what we have here is a parameter list
and a zero parameter constructor called "date" and a three parameter constructor
called "date" defined for this class. Now, if you go over on the other side, I've illustrated how you
would implement those things. The one with three arguments is
perhaps easier to understand. Obviously, the intent here is
to initialize the date with d, the month with m, and the year with y.
And that's what that constructor does. And it's - so that is the
implementation of that function. And I'll - I'll explain in a minute
exactly what's going on here. But notice that I also have the
default - the parameter list one. And what that's going to
do is also initialize day. But it's going to make a system
call to get the day of today, the day you're creating
the object and the month of today and the year of today. So if you don't specify a day,
month, or year, then it will come to life with today's date in it. Now, here's how those
work with declarations. What I've declared is two date objects. D1 has no arguments. And so that is an implicit call
to the no-argument constructor. So d1 will come to life
with today's date in it because of the way we specified
the initialization process. Date - d2 will come to life with the
11th day of the 9th month of 2001 because we are specifying
day, month, year of d2. And that represents a call
to the other constructor. So if you declare an object
with no params at all, that's a call to the
parameter list constructor. And that'll be used to
create that object. If you specify parameters, then the - then that's a parameterized
constructor would be called and use those parameter
to create the object. [ Silence ] Now, there's this notion
of default constructor. The default constructor is a
little bit of an ambiguous term. If you do not declare any
constructors in your class definition, which you're allowed to do. You can just simply not
have any constructors. If you do that, then the compiler will
create a parameter list constructor. And of course, that will be
called the "default constructor." And it will - it will not initialize
anything [inaudible] just - it's just be a block of memory
structured to hold the variables that you have declared in there. If you create any constructor at all
in the class, you define one at all, any kind, whether or
not it has parameters, then the compiler will not
create a constructor for you. It will assume you wanted the
set of constructors you have; and that's the ones you will get. So let's say you have -
you created a class "date" and you gave it the three
parameter constructor only, then there would not be a zero parameter
constructor created by the compiler. If you want a zero parameter
constructor, you would need to create it yourself
and declare it just as we did. [ Silence ] Now, so the ambiguity is that most
people, including myself will call - if there is a constructor with
no parameters, we will then call that default constructor, even if you've
created it and the compiler didn't. In fact, if there is
one with no parameters, that's the default constructor. And it can be created
really in three ways. Way one is you don't declare
any constructors at all, and the compiler creates one for you. Way two is you create a constructor
specifically with no parameters, and that then with no
parameter or constructor, which will call the default constructor. The third way is you could have
a constructor with parameters and supply default arguments
for all of the parameters. And that becomes the way
a default constructor or parameter-less constructor
is defined. So notice a number 3 here, we have
date with a 3 parameter constructor. But each of them has a default value. I guess all of them is zero,
but that's just what I wrote. But that gives - that gives a
compiler a way of creating an object when you don't specify arguments. Right? It just sees a 000. And so if you create a date with that - and that constructor is
your only constructor, then you'll get a - or default. Your date with no arguments
will be the date 000, which I'm not sure is a
legitimate date; but nevertheless. [ Silence ] Of course, if you - if you had
a three parameter constructor, as I've illustrated it in Item 3
there, with default arguments for all of the parameters and
then you also attempted to have a 0 argument
constructor different from that, then you'd get a compiler error
because you would have an ambiguity that you would be telling the
compiler two distinct ways of initializing an object when
no parameters are specified. And it would - the message
would be something like this function is ambiguous
because I see two different ways of implementing that function. Even if your implementations
resulted in equal objects, you'd still get the compiler error. And that goes back to the whole
concept of function overloading. The compiler has to be able
to tell them apart based on the parameter [inaudible]. If you have a function with no
parameters and another function with the same name and parameters but
all the parameters have default values, then that will be a conflict
that the compiler [inaudible]. You'll get an error message. [ Silence ] Okay. I guess this is the next slide. It appeared by magic. But I must have touched something
on the little machine there. So here we have, I guess, a review
of constructors for class "date." So notice that we have date,
class and then we have "date" with parameters though as constructor. And we have date with three
parameter constructor. And the things we had before. Addyear, Addmonth, Addday. And the same private data as before. So what we've done is just add
constructors to the previous date class. And now my - the implementation
of those two constructors is in the box on the right-hand side. And so now in the box on the lower
left, you see I can declare date d1. And d1 will - that will be
created with a default constructor. So d1 will now come to life
with today's date in it. D2 will come to life with 11-9-01. [ Silence ] Okay. I think I must have
gone backwards last time. Okay. So now I want to talk
about initialization lists. In that constructor - in a [inaudible]
with arguments or without arguments for that matter when you have class
variables that need to get initialized. And what I showed you before, we were
doing those initializations in the body of the -of the function definition. So before we did those
initializations here. And what we have done
is moved them to here. And there is a subtle distinction
between those two things. And the one I'm illustrating
now is by far preferred. And there will be instances where this
is the only way you can implement a constructor with initialization lists. And the basic idea is what happens when you create an object,
let's say a date object. There's kind of two steps. The first step is get a block of
memory that is sized appropriately to hold the data for the class. And the second step is to prepare that
memory - or initialize that memory. When you initialize with
an initialization list, what you're doing is guaranteeing that at the time the
memory allocation is made, the correct values are
written into memory. Whereas, if you did it
inside the braces, once you get into that opening brace,
the memory has already been allocated. So what happens in that case
is the memory gets allocated with the random stuff in it. And then the random stuff
gets overwritten by what you really wanted to begin with. So it's much better to have the memory
come prepackaged with the right data in it than get the wrong random data
in it and then have to overwrite it after the object is created. So by specifying how things get
initialized and [inaudible], you're getting the - you're getting
the class initialized as it is created as opposed to having to overwrite the
information that was erroneously put in there at the time it was created. Wait until it is created,
and then overwrite it later. [ Silence ] Now, at this stage, you can get by
with either way of initializing. The compiler will let you get by
with either way of initializing. But we won't. We're going to insist that you
initialize it with an Init list. Later on when you get to polymorphism, that is to say object
[inaudible] programming, your Project 1 that you
have to write, it will be - the compiler will not let you -
there'll be no way to even make sense of initializing in the body. You will have to use
an initialization list. [ Silence ] So how do you organize code here? It's very much like the way we
organize code for functions. You have a header file and code file. In the header file, what you do
is you put your class definition. That's the thing that says "class, name
of class, opening brace, public sector, private sector, closed
brace, and semicolon." And in a separate file,
you put the implementation of the class member, the functions. Now, those class member functions
can be precompiled to object code. Of course, the class definition
is just the definition. It doesn't really compile. Now, there's also this
concept of structs, which you may have seen
in your COP3014 Class. You may also have seen if you
happened to take a C Class. C structs came to C plus plus from C.
Structs came to C from earlier concepts of programming where you
need a way to house data. And this was known as a data record. But back in the old IBM, Cobalt days
they had something called a "record." And a record was simply an encapsulated
place of memory with fields of data in that encapsulated memory space. And those fields are typically
accessed with dot notation. So you could have a student record, and
that student record would have a name, a student number, and who knows
what else, an address and so on. And so you'd have a student
rec x even way back in Cobalt. And then x dot name would
be the name of that student. X dot address would be the
address for that student. X dot sn would be the student
number of that student and so forth. So that was way back
in the days of Cobalt. And you can see how that would be
very convenient to collect data about a person all in one
thing called a record. Well, C - the designers of
C knew the utility of that; so they devised this thing called
"struct" or "structure," and it was just like a data record out of Cobalt. And it allowed you to declare
inside of that struct data fields and to populate those fields. And those fields could have names. So it worked just like Cobalt. You could have a student record
in C and x as a student record, x dot name would be the name. x dot sn would be the
student number, and so forth. Very, very similar notation. What C plus plus did is build on
that concept to create objects. So our objects have data
just like a struct and just like an old Cobalt record. But the objects can now
also have functionality. So for example, if your student
record had all of your grades in it, then you could have a
function called "GPA" that - and so you could do x dot GPA, and
that function would compute a GPA based on the grades in that
record and return a value. And that would be functionality
associated with the record. That's what a class is. And the whole private, public
business is slightly different. So C plus plus inherited struct from
C; but C plus plus allows structs to have functionality
just like classes do. In fact, in C plus plus, a struct and a class are virtually the
same - mean the same thing. The only difference is that in a class, the default access permission
is private; and in a struct, the default access is public. So I just illustrated that
here with this widget. You can have a struct called "widget." And it can have a constructor
and a couple of functions. And then you can say "private." And then you can put the day over there. That would be a way to
do it with structs. Since I didn't say anything at
the top, it was default public. Or you can do a class widget. You can start off with the data, and the default is private
unless I say "public." And so that data is private. Then I can say "public" and put the
functions in and get the same thing. Now, it's, of course, customary to
actually say "private" and "public" in both cases just to make it
clear to the reader - all right - the code reader, us, humans. And by the way, you can - you can
say "public" and do some stuff. And you can say "private"
and do some more stuff. And you can say "public"
again and do some more stuff. And you can say "private"
and do some more stuff. Then you could have public with
three functions that have to do with a certain kind of [inaudible]. And then say "private" and
declare those data fields. Then you can have public, put
some functions in that have to do with a different kind of
data; and then say "private" and put those data variables
and so forth. So that would be the first way
[inaudible] to switch back and forth. Okay. That's the last slide
in the session on class - the class - Introduction To Classes. So I am going to now
turn off this recording. [ Silence ]