IntroductionWelcome| 00:04 | Hi, I am Bill Weinman, and
welcome to C and C++ Essential Training.
| | 00:08 | In this course, we'll explore the C and C++
languages along with their standard libraries.
| | 00:14 | I'll start by showing you the basic syntax of C.
| | 00:17 | C syntax is the basis for both C and C++
as well as a number of other derived
| | 00:22 | languages like C#, Java, PHP, and many others.
| | 00:26 | I'll show you how to write classes and
templates in C++ so you can access all
| | 00:30 | the power of object-oriented programming.
| | 00:33 | This will enable you to take advantage
of modern programming techniques like
| | 00:37 | encapsulation, generalization, and code reuse.
| | 00:40 | I'll show you how to use advanced C++
features like inheritance and templates.
| | 00:45 | I'll show you the standard C library so
you can access resources on your system
| | 00:49 | like reading and writing
files and allocating memory.
| | 00:52 | We'll cover the C++ standard template
library providing powerful data types like
| | 00:57 | vectors, sets, cues, and associative maps.
| | 01:00 | We'll be covering these topics and
much more so that you'll have all the
| | 01:04 | resources you need to fully take
advantage of this powerful language.
| | 01:08 | C and C++ are among the most
powerful and widely used languages today.
| | 01:13 | Now let's get started with C
and C++ Essential Training.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you have access to the exercise
files for this course, you can use them to
| | 00:04 | follow along with the lessons as I present them.
| | 00:07 | Because this course uses C and C++,
you'll need a development environment
| | 00:11 | capable of compiling and running
console applications written in the latest
| | 00:15 | standard version of C and C++.
| | 00:18 | If you do not have a development
environment available, instructions are
| | 00:21 | included in this course for installing the
Eclipse C Development Tools for that purpose.
| | 00:27 | You'll need to copy the exercise
files folder to a location on your machine
| | 00:31 | where you can use it, for
example, in your Desktop folder.
| | 00:35 | Here in the exercise files folder,
you'll find a folder for each of the
| | 00:38 | chapters of the course.
| | 00:41 | For each of the lessons you'll make a
working copy of one or more of these files
| | 00:45 | and work with the copies.
| | 00:46 | That way if you need to start over,
you have the original files available to
| | 00:51 | make another working copy.
| | 00:53 | Some of the files are available for
non-premium members of lynda.com Online
| | 00:57 | Training Library like this
Operator Precedence chart and these WindowsSupport files.
| | 01:05 | The chapter folders are
available for premium members.
| | 01:08 | If you do not have access to the
chapter folders, you can easily follow along
| | 01:12 | and create files of your own.
| | Collapse this transcript |
| Prerequisites| 00:00 | In order to get the most out of this course,
you should have some programming experience.
| | 00:05 | The more experience you have the more
readily you'll be able to learn about C and C++.
| | 00:10 | But even if you are a relative
novice, you should still be able to follow along.
| | 00:15 | Either way you should be patient
with yourself and take your time.
| | 00:18 | C and C++ are not scripting languages
and while they have simple syntax that may
| | 00:23 | even look familiar, seemingly small
errors may seem overwhelming at first.
| | 00:28 | Remember, computers are very
picky about spelling and punctuation.
| | 00:32 | A parenthesis and a bracket may look
similar on your screen but they mean
| | 00:36 | entirely different things to the computer.
| | 00:39 | Because this course uses C and C++
you'll need a development environment capable
| | 00:44 | of compiling and running console
applications written in the latest standard
| | 00:48 | versions of C and C++.
| | 00:50 | If you do not have a development
environment available, instructions are
| | 00:54 | included in this course for installing the
Eclipse C Development Tools for that purpose.
| | 00:59 | As with all software development,
you'll want to do the exercise files for this
| | 01:04 | course on a system dedicated for this purpose.
| | 01:07 | C and C++ are systems languages, and
it is possible even easy to mistakenly
| | 01:13 | write a program that takes up all the
resources on your system or crashes it entirely.
| | 01:18 | You'll need to know how to find and
correct problems on your system and have the
| | 01:22 | time and freedom to do so
without losing critical resources.
| | 01:26 | Above all you'll need some patience.
| | 01:28 | Programming can be a frustrating
pursuit at times and with the compiled systems
| | 01:32 | language like C or C++, it can be even more so.
| | 01:36 | Take your time, type carefully, and
when you inevitably make mistakes,
| | 01:41 | patiently analyze those mistakes so
that you can recognize them when they
| | 01:44 | inevitably appear again.
| | 01:46 | This kind of experience is invaluable
and will serve you well for the long term.
| | 01:51 | Now let's go, have some fun learning C and C++.
| | Collapse this transcript |
|
|
1. Language OverviewAbout C| 00:00 | The C programming language
is the foundation of C++.
| | 00:04 | In fact, C is the basis of many modern
languages, including Java, JavaScript,
| | 00:09 | Perl, PHP, Python and many, many others.
| | 00:14 | Of course, C++ and Objective-C are
direct descendents of C and include
| | 00:18 | the entire C language.
| | 00:20 | Yes, the entire C language is included
in the definition of C++ and learning C
| | 00:25 | is an essential first step
on the road to learning C++.
| | 00:30 | Let me say this again in a deferent way.
You can not skip this step.
| | 00:34 | In order to learn C++, you must first learn C.
| | 00:38 | Developed by Dennis Ritchie at Bell
Labs in 1969, C was designed as an
| | 00:43 | alternative to assembly language for
creating operating systems utilities and
| | 00:48 | other systems level code.
C is a small language with only 32 keywords.
| | 00:53 | It's not what we would call
today a high-level language.
| | 00:56 | It is small, efficient, fast, and powerful.
| | 01:00 | If you consider layers of technology
in a computer system as a stack, C is
| | 01:05 | commonly used to write code at all levels,
with its most common usage at the lower levels.
| | 01:11 | Almost all firmware, almost all modern
operating systems and a great deal of
| | 01:15 | application software is written in C.
Why is C so popular?
| | 01:21 | Systems code written in C tends to
be small and fast, well-written C can
| | 01:26 | generate object code that is almost a small
and fast as code written in assembly language.
| | 01:32 | Code written in C is extremely portable.
| | 01:34 | C was originally designed
for writing operating systems.
| | 01:37 | For example, the UNIX operating system
was written in C, and it runs on many,
| | 01:42 | many different processors
and hardware configurations.
| | 01:46 | This is possible because so much of
the operating system compiles and runs on
| | 01:50 | many different machines,
architectures and processors with little or no
| | 01:54 | modification to the source code.
| | 01:56 | This is equally true of
applications written in C.
| | 01:59 | The language itself is relatively small and
easy to learn, yet its simplicity is deceptive.
| | 02:06 | It gives you such access to the machine that
is actually very rich and powerful language.
| | 02:11 | C is a low-level language that
means that it's close to the machine.
| | 02:16 | It doesn't have a lot of features, but
it compiles to tight, fast, efficient
| | 02:20 | code that's what's C is good at, that's why
people continue to use C after over 40 years.
| | 02:26 | C is an imperative language.
| | 02:29 | This means that the code is described
as statements, subroutines are called
| | 02:33 | functions and arguments
are always passed by value.
| | 02:35 | C is a block-oriented structured
language that is code happens in blocks and the
| | 02:42 | blocks are structured to enhance clarity.
| | 02:44 | This is to improve quality and
maintainability of your code.
| | 02:47 | C is strongly typed;
| | 02:50 | this means that each
variable must have a declared type.
| | 02:53 | Type declarations are parsed at compile
time and they cannot change during the
| | 02:58 | life of the variable.
| | 02:59 | The advantage of a strongly typed
language is that performance is significantly
| | 03:04 | improved over similar
dynamically typed languages.
| | 03:07 | In a dynamically typed system, runtime
processing power is used to determine
| | 03:12 | the type of a variable and create
working copies with the appropriate data
| | 03:17 | structures for every variable and even
repeat these actions when a variable is changed.
| | 03:22 | By determining the type of variable at
compile time, all of this overhead is eliminated.
| | 03:28 | The first written standard for the C
programming language was a book called The
| | 03:31 | C programming language by Brian W. Kernighan and Dennis M. Ritchie.
| | 03:36 | The book came to be effectually known
as K&R and the version of the language
| | 03:40 | documented was called K&R C.
| | 03:43 | The first edition of the
book is long out of print;
| | 03:46 | the revised version currently in print
documents the next later version ANSI C.
| | 03:51 | The ANSI C standard was ratified in
1989 and adopted by the ISO in 1990.
| | 03:57 | So you'll see it
referred to as both C89 and C90.
| | 04:01 | The first truly standardized C, this version
is the basis for most of the C we use today.
| | 04:07 | ANSI C introduced function prototypes,
void pointers and locals all of which are
| | 04:12 | considered fundamental to C today.
| | 04:14 | C99 is mostly compatible with ANSI C with a few
new features and a few tighter restrictions.
| | 04:21 | Notable enhancements include C++
style one-line comments introduced by two
| | 04:26 | forward slash characters and
variables can be declared anywhere within a
| | 04:30 | block instead of only at the top of a block.
| | 04:32 | C11 is the latest standardized version,
and it codifies features that have
| | 04:37 | been implemented by many compilers, including a
more detailed memory models for threaded code.
| | 04:43 | Removal of the get function improved
Unicode support, anonymous structures and
| | 04:47 | unions and some optional features.
| | 04:50 | This course uses C11 but since most
of the changes since ANSI C have been
| | 04:55 | incremental, most of what you learn
will apply to any standard C version.
| | 05:00 | Because C is the foundation of C++ and
the complete C language is included in
| | 05:05 | the definition of C++, this course
contains tutorials sufficient to learn the
| | 05:10 | basics of the C language.
| | 05:11 | Here is a list of chapters you may
view in order to learn C from this course.
| | 05:16 | Chapter 2 includes instructions on
installing the environment for following
| | 05:20 | the exercises along with a simple hello world program
for testing your development environment.
| | 05:25 | Chapter 3 includes an overview of
the basic syntax of the C language.
| | 05:29 | Charter 4 covers the C preprocessor
and essential part of the language.
| | 05:34 | Charter 5 describes the types of data used in C.
| | 05:39 | Chapter 6 covers the rich set of
operators providing in the C language.
| | 05:43 | Chapter 7 discusses the use of functions
and Chapter 11 covers the C standard library.
| | 05:50 | These chapters will give you a
thorough introduction to the language and with
| | 05:53 | little experience enough to
begin writing C programs on your own.
| | 05:57 | The C programming language is the basis
of C++ and is included completely in the
| | 06:02 | definition of the C++ language.
| | 06:04 | Learning C is an essential first
step on the path to learning C++.
| | Collapse this transcript |
| About C++| 00:00 | C++ was developed in the late 1970s by
the Danish computer scientist, Bjarne Stroustrup,
| | 00:06 | as a set of enhancements to
allow object-oriented programming in C
| | 00:10 | and today it is one of the most
popular programming languages in the world.
| | 00:14 | C++ is a powerful and flexible general
purpose programming language that allows
| | 00:20 | programming in a number of different
paradigms, including object-oriented,
| | 00:23 | procedural, functional and generic programming.
| | 00:26 | C++ extends the C language adding many
powerful features while retaining as much
| | 00:33 | of C's efficiency and utility as possible.
| | 00:35 | C++ is a very popular language and
after 30 years, it's still widely considered
| | 00:41 | a best practices choice for many
types of projects, including large scale
| | 00:45 | systems and applications coding.
| | 00:48 | If you consider the layers of technology
in a computer system as a stack, C++ is
| | 00:52 | used to write code at all levels except
firmware with its most common usage at
| | 00:57 | the application level.
| | 01:00 | Today, vast numbers of medium to large
scale applications are written in C++.
| | 01:05 | The list is huge and includes
Microsoft Office, Adobe Photoshop, Illustrator,
| | 01:10 | InDesign, Firefox, Google Chrome,
provisioning service and billing systems for
| | 01:15 | major phone and networks, even major web
sites like Amazon, Facebook, and Google
| | 01:20 | are either written in or have
significant backend resources written in C++.
| | 01:24 | Operating systems, including every
version of Windows since 1.0, parts of UNIX
| | 01:31 | that aren't written in C, major parts
of OS X, other parts are in Objective-C
| | 01:35 | which is also based on C.
| | 01:37 | In fact, most other programming languages,
including Java, PHP, Python, and Perl
| | 01:43 | are written in C or C++.
| | 01:44 | C++ is made up of a number of components,
parts of which require understanding
| | 01:50 | distinct sets of grammar.
| | 01:52 | You can think of it as five
distinct but connected languages.
| | 01:56 | As part of the C language
definitions, the C preprocessor is also
| | 01:59 | incorporated in C++.
| | 02:02 | The C language itself is the basis of C++,
and is entirely incorporated in its definition.
| | 02:08 | C++ classes and objects are used for
object-oriented programming patterns.
| | 02:13 | C++ templates are part of the C++
language and the C++ Standard Template
| | 02:20 | Library sometimes called the STL which
provides a tremendous amount of common
| | 02:25 | functionality along with the C and C++
standard libraries is also a part of the C++ standard.
| | 02:33 | The first standard for C++
was ratified by the ISO in 1998.
| | 02:37 | This is commonly referred to as C++98.
| | 02:41 | C++03 was essentially a bug fix release,
so it's rarely referred to on its own.
| | 02:47 | Most compilers that support C++03
simply refer to it as C++98.
| | 02:53 | Technical Report 1 or TR1 is mostly a
set of library extensions, including
| | 02:57 | regular expressions, smart pointers,
hash tables, and random number generators.
| | 03:02 | Most of this became part of C++11.
| | 03:05 | Ratified in August, 2011, C++11 is the
first real extension of the C++ Standard.
| | 03:12 | It provides a number of new features,
including a range based for loop, type
| | 03:15 | inference, lambda functions, and
unambiguous null pointer constant, and most of TR1.
| | 03:22 | This course uses C++11 and the latest
versions of all the major compilers in use
| | 03:28 | today support C++11.
| | 03:31 | To thoroughly learn the C++ language, I
suggest that you take this entire course in order.
| | 03:37 | On the other hand C++ is a big subject
you may want to skip around some, here's
| | 03:42 | an overview of what is covered and where.
Chapters 2 through 7 cover the C language.
| | 03:47 | C provides all the basic syntax for C++.
So this is a vital foundation for learning C++.
| | 03:55 | Chapters 8 and 9 cover the
object interface for C++.
| | 03:58 | This is essential for all object-
oriented programming and concepts and is used
| | 04:04 | in other parts of the language,
including templates and the STL.
| | 04:08 | Chapter 10 covers the
templates interface for C++.
| | 04:11 | Templates are used in the Standard
Template Library so you'll need to understand
| | 04:15 | this in order to fully take
advantage of many C++ standard features.
| | 04:20 | Chapter 11 covers the C Standard Library
which provides many common functions for C++.
| | 04:27 | Chapter 12 covers the Standard Template Library.
| | 04:30 | The STL provides many higher-level
functions to C++ like strings, containers,
| | 04:36 | algorithms, iterators, and other utilities.
| | 04:39 | Chapter 13 covers some of the
new features in the C++11 Standard.
| | 04:44 | The C++ programming language is
clearly one of the most important languages
| | 04:48 | in computing today.
| | 04:50 | It is the go-to language for many large
and small projects and forms the basis
| | 04:55 | of many other popular languages
like Java, C#, PHP and many others.
| | Collapse this transcript |
|
|
2. Getting StartedUsing Xcode with the exercise files| 00:00 | In this movie, I will show you how to create a
workspace in Xcode for following along with
| | 00:04 | the exercises in this course.
| | 00:06 | I used Eclipse to demonstrate
the examples in this course.
| | 00:10 | I chose Eclipse because it runs on all the
popular platforms today, but you don't need
| | 00:14 | to use Eclipse to follow
along with the exercises.
| | 00:18 | Apple's Xcode is an excellent development
environment and if you're a modern Mac it
| | 00:22 | maybe a good choice for you.
| | 00:24 | Xcode is an IDE, an
Integrated Development Environment.
| | 00:28 | It includes editors, compilers, and other
development tools and they're integrated into
| | 00:33 | an environment that makes them more easy and pleasant
to work with than the tools would be on their own.
| | 00:38 | The current version of Xcode as of late 2012 requires
an Intel-based Mac running OS X Lion 10.7 or later.
| | 00:47 | If you're running an earlier version of OSX you
will not be able to use a current version of Xcode.
| | 00:52 | In that case you should stop right here and
instead install Eclipse with an updated GCC
| | 00:57 | compiler toolchain.
| | 00:59 | See the movies installing Eclipse with GCC on a Mac
and upgrading GCC on a Mac for further instructions.
| | 01:06 | The compiler that ships with
Apple's Xcode is called LLVM.
| | 01:10 | LLVM originally stood for Low Level Virtual
Machine, but this initialism has been abandoned
| | 01:15 | as the compiler toolchain is not really
limited to development of virtual machines.
| | 01:20 | LLVM is actually a compiler infrastructure that
uses a front-end for each supported language
| | 01:25 | or language group.
| | 01:26 | The front end for C/C++ and Objective-C
is called Clang short for C language.
| | 01:33 | As of the time of this recording the current
version of Xcode is 4.5 and the version of
| | 01:38 | Clang that is shipping
with Xcode 4.5 is Clang 4.1.
| | 01:42 | This is the first version of Clang with
sufficient support for C++11 for use with this course.
| | 01:49 | When this course was originally released, the
shipping version of Clang was not sufficient
| | 01:52 | to support this course, at that time I recommend
installing Eclipse and upgrading GCC to the latest version.
| | 01:59 | This is no longer necessary on a
modern Mac with the latest Xcode.
| | 02:03 | Xcode also ships with legacy
support for an older version of GCC.
| | 02:08 | This GCC compiler is far too old to support all the
language features used in this course. Do not use it.
| | 02:14 | Now let's take a look at how to set up a workspace in
Xcode for following the examples in this course.
| | 02:19 | In order to proceed you will need to have
installed Xcode 4.5 or later either from the
| | 02:24 | App Store or from an Apple developer account.
| | 02:28 | Xcode is free; it requires a modern Intel
-based Mac running OS X 10.7 or later.
| | 02:35 | I've already installed Xcode on this Mac.
| | 02:37 | So let's go ahead and
proceed with the installation.
| | 02:40 | The first thing you're going to need to
do is to install the Command Line tools.
| | 02:44 | So we'll come up here to the Xcode menu and
select preferences or you can press Command+comma,
| | 02:50 | as you can see there in
the shortcut on the right.
| | 02:53 | And you will want to select
Downloads here from the top menu.
| | 02:56 | It may be on General or wherever you last
used it and you'll want to select Download.
| | 03:02 | From this little selector here, you'll want
to select Components which is the one on the
| | 03:07 | left and you see Command Line tools is the
third one down and here it says Installed
| | 03:12 | next to Command Line tools.
| | 03:14 | If the Command Line tools were not already installed
there would be a button there that says Install.
| | 03:19 | You would want to press that button and wait
while the Command Line tools are installed,
| | 03:23 | and you'll probably have to type your
password at some point during that process.
| | 03:27 | So now that the Command Line tools are
installed we'll go ahead and close this and we will
| | 03:30 | create a new workspace.
| | 03:33 | So you don't want to create a file or project.
| | 03:35 | At this point you want to create a workspace.
| | 03:37 | So that's from the File
menu > New > Workspace.
| | 03:40 | So I am going go ahead name this CppEssentialTraining
and I strongly recommend that you do not use
| | 03:47 | spaces in your project and
workspace file names in Xcode.
| | 03:52 | Some of the tools are a little bit finicky about
that and a space can be interpreted differently.
| | 03:56 | I don't use spaces. I don't use any special
characters. I might use an underscore, I might
| | 04:01 | use a dash, but in this case just
CppEssentialTraining like that will work fine.
| | 04:06 | I am storing it in my documents folder and you'll
notice that that's right off of my home folder.
| | 04:11 | You can store wherever you like
just remember where you stored it.
| | 04:14 | So I am going to press save
and now we have a workspace.
| | 04:19 | Now the first thing we want to do is to add
a folder reference to our exercise files.
| | 04:22 | So we are going to press this little plus
down here at the bottom and I'm going to say
| | 04:27 | Add Files to our workspace.
| | 04:29 | I am just going to go my desktop which is
where I have my exercise files stored and
| | 04:36 | select the ExerciseFiles folder.
| | 04:38 | If your exercise files are someplace
else, you'll need to select that.
| | 04:42 | Do not check copy items, because you don't
want to copy this in your project, you want
| | 04:46 | it to just link to it and you just want to
select this one at the bottom that says Create
| | 04:50 | folder references, and then I'll select Add, and now
we have our exercise files here in our workspace.
| | 04:58 | So I can open this disclosure triangle and that
one and I see that I've got the files there.
| | 05:04 | So what we are going to do is we are going
to now create a project for compiling and
| | 05:07 | running these exercises.
| | 05:08 | And we will be copying files, not just linking
to them, but actually copying them from here
| | 05:14 | and into our project and then deleting them
from our project when we are done with them.
| | 05:18 | So let's go ahead and add a project.
| | 05:19 | I am going to press this plus down
here and I am going to say New Project.
| | 05:24 | And in this case, I want to make sure I select
OSX and Application and Command Line tool,
| | 05:31 | and that's what you want, because all of
these exercises are simply Command Line tools.
| | 05:36 | The idea of these exercises being Command
Line tools is to get everything else out of
| | 05:40 | the way so that we can pay
attention to the language feature.
| | 05:44 | So we don't want to have a GUI application
where we have to make lots of calls and callbacks
| | 05:48 | and things like that, because that just gets in the
way of understanding the actual language feature.
| | 05:53 | These are very simple Command Line tools and
this is the way that we want this project made.
| | 05:58 | So we select Command Line
tools and then press Next.
| | 06:01 | I'm going to name my project.
| | 06:03 | I am just going to call it Working.
| | 06:04 | In Organization Name you
can put whatever is there.
| | 06:07 | That's just the name of
my account on this Mac.
| | 06:10 | For Company Identifier this is
typically in reverse domain formats.
| | 06:14 | So if you have a domain name, you can use it or
you can just use example.com, which is what I do.
| | 06:19 | So I will just say com.example and you see
it puts the .Working already at the end of
| | 06:25 | it for the bundle identifier.
| | 06:27 | It's not even going to use that, but it requires that
you can't really create this project without it.
| | 06:31 | For type you want to have it be a C++ project
which will allow you to use both C++ and C.
| | 06:38 | You want to uncheck Use
Automatic Reference Counting.
| | 06:41 | It's not actually even available in C++, but
it does add complexity to the executables
| | 06:47 | and we don't need that.
| | 06:48 | We are not going to use it.
| | 06:49 | So you just uncheck that and then press Next.
| | 06:54 | Now again, I am just going to go ahead and
store it under Documents and you can store
| | 06:58 | it wherever you like as long as
you remember where you stored it.
| | 07:01 | I am going to uncheck the Create a local
git repository, because we don't need that.
| | 07:07 | We are not going to be using it.
| | 07:09 | For this project you are going to be
creating files and deleting files.
| | 07:11 | You are not really going to be
building any project with it.
| | 07:15 | So the git repository
will just get in the way.
| | 07:18 | And you are going to make sure that Add to
has CppEssentialTraining, our workspace, and
| | 07:25 | Group also has CppEssentialTraining.
| | 07:27 | So we will go ahead and press Create.
| | 07:33 | There we now have our Working project.
| | 07:36 | Now let's check our build settings
and make sure that they're correct.
| | 07:38 | We are going to select our project and under
Build Settings you want to select Basic and
| | 07:43 | Combined up here, otherwise it just
gets to be too hard to find things.
| | 07:49 | Then scroll down to where
you see Apple LLVM compiler.
| | 07:57 | And you want no Optimization for your debug
just like that, and that appears to be the
| | 08:01 | default, and then under C Language Dialect this is
under the Language part of LLVM compiler 4.1.
| | 08:10 | Under C Language Dialect you
want GNU99 just like that.
| | 08:15 | So you see these are the different choices.
| | 08:17 | If GNU99 is not the one that's selected you
want to select GNU99 and you want GNU++11.
| | 08:24 | Actually C++11 would work or GNU
++11 would work for this one.
| | 08:28 | That's under C++ Language Dialect.
| | 08:31 | The defaults here are probably fine, but if
they're not what you see here than you want
| | 08:35 | to change, and likewise for the Standard
Library, you don't want libstndc++ like that.
| | 08:42 | You want just libc++ like this.
| | 08:44 | That's the GNU library and since we are
not using the GNU compiler it won't work.
| | 08:49 | You want to make sure you
have the LLVM version selected.
| | 08:53 | So if these are all correct we will come
over here now and just select this main.cpp in
| | 08:59 | the working project.
| | 09:00 | You will notice that it's just a
simple Hello, World! Program.
| | 09:03 | We are not going to use that.
| | 09:04 | So we are going to go ahead and delete it.
| | 09:06 | So with this selected I am going to press the
Delete key on this keyboard and I am going
| | 09:12 | to actually Select Move to Trash, not
just Remove Reference, but Move to Trash.
| | 09:16 | That's really important because this has a
main in it, you see, and you can't have more
| | 09:21 | than one main and each of examples has a main.
| | 09:24 | So we really need to remove
this from the project entirely.
| | 09:27 | So I select Move to Trash and I
do the same with this Working.1.
| | 09:33 | That's a man page.
| | 09:34 | It assumes that since we are building a
command line application that we are going to man
| | 09:37 | page and this is in this ROFF language.
| | 09:40 | It's probably NROFF.
| | 09:43 | But it's not anything we really
need to know about or care about.
| | 09:45 | This is how man pages are made and
we are not going to make a man page.
| | 09:48 | So we are just going to delete this file and
I am going to select Move to Trash again and
| | 09:54 | there we have it.
| | 09:55 | So now we have our working project and this
working group inside, they called it a group.
| | 10:00 | It's very much like a folder.
| | 10:02 | This working group is where we're
going to be putting our files.
| | 10:05 | I am also going to hide
this information panel.
| | 10:08 | You might want to leave it there, but for my
purposes because I've such limited screen
| | 10:11 | real estate here I am just
going to get rid of that.
| | 10:14 | Now before we go any farther there
is one more thing we need to do.
| | 10:17 | We need to edit our Scheme.
| | 10:20 | So you see this is Scheme area up here and
we have a working scheme and we also have
| | 10:24 | it compiling for the 64-bit Mac and
you'll have whatever is there for your Mac.
| | 10:29 | It will probably be a 64-bit Mac if
it's an Intel Mac running OSX 10.7.
| | 10:35 | But you're not going to select that.
| | 10:37 | You're instead going to
select the word Working.
| | 10:39 | If you have your Working projects selected
you'll have this working up there for the scheme.
| | 10:42 | You're just going to say
Edit Scheme under that menu.
| | 10:47 | So here it says Working, Scheme, it says
Destination, My Mac 64-bit, and down here you have all
| | 10:53 | of these profiles.
| | 10:54 | Within it you want to select Run Working and
then come over here and select arguments in
| | 10:59 | this little menu there.
| | 11:01 | Then arguments passed on launch.
| | 11:02 | You are going to press the plus sign to add an
argument, and just type the word one, and then
| | 11:07 | you will press plus sign again and type the
word two, and press the plus sign one more
| | 11:12 | time and type the word three.
| | 11:14 | Once you have one, two, and three in there
you are going to press OK and that's command
| | 11:20 | line arguments and we will see how
those work later in this movie.
| | 11:23 | So now we are ready to go.
| | 11:24 | We are going to open up the ExerciseFiles
disclosure triangle and open up Chap02 and
| | 11:29 | select version-test.cpp.
| | 11:32 | Now what I am going to do is I am actually
going to copy this into my working project.
| | 11:36 | I'm not going to work on it here.
| | 11:38 | In fact, it won't compile here,
because this is not within a project.
| | 11:41 | I am going to make a copy of it.
| | 11:43 | I am going to drag it up to Working and you
see how it's highlighted the Working folder
| | 11:49 | icon there in blue and there's a plus sign.
| | 11:52 | I am not pressing any modifiers on the
keyboard, I am just dragging the file up there.
| | 11:56 | You don't want to put in Products, you don't
want to put it up here, you want to put it
| | 12:00 | right in there in that Working folder.
| | 12:01 | So I am going to let that go and I am going to check
Copy items, because we want to actually make a copy now.
| | 12:08 | If we allow it to be a reference, then we
will be modifying the original and that defeats
| | 12:13 | our purpose of making a copy.
| | 12:14 | I want to be able to make a copy. I want to
be able to modify it and change it and be
| | 12:17 | able to revert back to the
original, if we need to.
| | 12:20 | So we have to leave these
files alone in our file system.
| | 12:23 | So we are making a copy of
it there under Working.
| | 12:25 | Check the Copy box, check create groups for
any added folders, and Add to target Working,
| | 12:32 | that's very important, and Finish.
| | 12:35 | Now we want make sure we
actually select this one.
| | 12:37 | We don't leave this one in the file system
selected, because we are going to edit it.
| | 12:41 | So we select that one there.
| | 12:43 | Before you press the Run button actually,
you want to come over here to Product and
| | 12:47 | run Clean just in case you've
compiled something before in this project.
| | 12:51 | Now you're going to come over here
press the Run button and it will compile.
| | 12:55 | It says Build Succeeded, and
it runs it, and there it is.
| | 12:59 | There is my output.
| | 13:01 | So you see that it says GCC version 4.2.1,
and that is actually irrelevant.
| | 13:07 | That's the equivalent GCC version.
| | 13:09 | We are not actually running GCC.
| | 13:11 | We are running LLVM and Clang.
| | 13:13 | So you notice the version string says 4.2.1
which is the last version of GCC that ever
| | 13:19 | shipped with Xcode, and they are not shipping anymore,
and they won't ship anymore for a lot of reasons.
| | 13:24 | Instead they're using Clang and so it
says 4.2.1 compatible Apple Clang 4.1.
| | 13:31 | So this is actually the string
here that you're concerned with.
| | 13:34 | It needs to say 4.1 or higher and if
it does, then you're in good shape.
| | 13:40 | So we want to do one more thing here.
| | 13:41 | We want to check it will
actually compile C++11 features.
| | 13:45 | So you select these lines here and I'm pressing
Command+/ on my keyboard and that will uncomment
| | 13:54 | those lines, and Command+S will save it, and
I am going to press this Run button again
| | 14:01 | and now it's done a whole lot more stuff.
| | 14:03 | So I am going to scroll up here
so we can see the whole thing.
| | 14:06 | After version string we have one, two, three
which is from this vector that be created
| | 14:11 | using the Initializer List feature from C++11.
| | 14:15 | This will not compile on an
older version of the compiler.
| | 14:19 | It won't compile on older Clang.
| | 14:21 | It won't compile on GCC.
| | 14:23 | This is confirming that you're actually using
the current version of Clang and that it's
| | 14:27 | set up to compile with the C++11 features.
| | 14:32 | So if that works then we print it out using
another C++11 feature the range based for loop.
| | 14:38 | This is a new construct in C++ and
you see that that works as well.
| | 14:43 | We have this one, two, three.
| | 14:45 | So we've now confirmed that we have working C++
11 compiler and that it's actually working.
| | 14:53 | So we are going to go ahead and delete
this version test from our Working project.
| | 14:56 | I select it and I press the Delete key on my
Mac keyboard, and select Move to Trash, and
| | 15:03 | now we are going to copy over
this file that says c99.c.
| | 15:07 | I am just going to drag that up into
my Working project and let it go.
| | 15:12 | These haven't changed.
| | 15:13 | So I have copy items, I have
create groups, I have checked working.
| | 15:16 | I press Finish and now I am going to
select this file and there it is.
| | 15:23 | This is a simple C file. This is not C++.
| | 15:25 | You notice it has .c in the filename.
| | 15:28 | That makes it C not C++.
| | 15:31 | I want to come up here to
product and run Clean.
| | 15:33 | This is very important.
| | 15:34 | You need to do that to make sure that it will
compile this and not add it to the other one,
| | 15:39 | and I'm going to select Run.
| | 15:42 | So this is testing that our compiler actually
runs C99 code as opposed to older versions of C.
| | 15:49 | Whatever it says here under 0 is just going
to be the actual location of the working code
| | 15:54 | that's been compiled.
| | 15:56 | That's not really relevant, but if 1, 2, and
3 say one, two, three with the words, that
| | 16:01 | means that it's grabbing the command line
arguments and it's printing them out with
| | 16:04 | C99 feature right here which allows you to
both declare and initialize a variable inside
| | 16:10 | a for loop control structure.
| | 16:13 | So we can see that that's working right there, and we
have now successfully created our Xcode workspace.
| | 16:21 | So I am going to go ahead and delete this
from my Working project, and I'm going to run
| | 16:28 | Clean, and now we are ready to
proceed with the exercises.
| | 16:35 | So you now have a working Xcode workspace for
following along with the exercises in this course.
| | 16:41 | Xcode is an excellent IDE and
LLVM is becoming a superb compiler.
| | 16:46 | This combination provides a great
environment for the exercises in this course.
| | Collapse this transcript |
| Setting up Eclipse with LLVM and Clang on a Mac| 00:00 | In this movie, we're going to install the
Eclipse C Development Tools on a Mac using
| | 00:05 | the LLVM toolchain provided with Xcode.
| | 00:08 | Note that it's not necessary to install
Eclipse in order to take this course.
| | 00:12 | Even though I used Eclipse for the exercises
in videos, you may prefer to use Xcode on
| | 00:17 | your Mac and that will work fine.
| | 00:20 | Please see the movie Using Xcode with the
Exercise Files for instructions on setting
| | 00:24 | up Xcode for use with this course.
| | 00:27 | I used Eclipse for the examples in this course
because it's convenient for teaching purposes.
| | 00:31 | It allows me to demonstrate the examples in
a way that is accessible to students on any
| | 00:37 | of the three major platforms
today: Windows, Mac, and Linux.
| | 00:41 | This is the only reason I
used Eclipse for this course.
| | 00:43 | I normally do my development work with whatever
tools are supported on the platform I'm working
| | 00:48 | on and I encourage you to do the same.
| | 00:51 | In order to install Eclipse on a
Mac, you'll need a few things.
| | 00:54 | You'll need a relatively modern Mac, running
Xcode with the command line tools installed.
| | 00:59 | The current version of Xcode requires an Intel
based Mac running OS X Lion, 10.7 or later.
| | 01:06 | If you're running an earlier version of OS X,
you will not be able to use a current version
| | 01:10 | of Xcode and in that case, you should stop
right here and instead install Eclipse with
| | 01:16 | an updated new GCC Compiler toolchain.
| | 01:19 | See the movie, Installing Eclipse with GCC on a
Mac and Upgrading GCC on a Mac for instructions.
| | 01:27 | You will also need the
Java Runtime Environment.
| | 01:29 | If you don't have Java installed, OS X will offer to
install it for you the first time you run Eclipse.
| | 01:36 | So I'm going to launch Xcode and I'm just
going to bring up About Xcode here and you
| | 01:43 | can see that this is Xcode 4.5.2.
| | 01:47 | Any version of Xcode version 4.5 or
higher will work for this purpose.
| | 01:52 | Xcode is free from the App store.
| | 01:54 | If we come in here to Preferences and under
the Downloads tab and under Components, you'll
| | 02:00 | see that I have installed
the command line tools.
| | 02:03 | You'll need this in order to run LLVM with
Eclipse, and so I have the latest Xcode installed
| | 02:08 | and I have the command line tools installed,
I'm just going to click this Check for updates
| | 02:13 | right now, here it says no updates available, and
I have always checked this little check box.
| | 02:19 | These updates are the developer tools and you
need to keep these as updated as possible.
| | 02:24 | So Xcode is free from the Apple App Store
and you need a free developer account and
| | 02:30 | then you can install the command line tools and
that's what you'll need in order to do this.
| | 02:35 | So I'm going to close this, I'm going to
close Xcode and now we'll install Eclipse.
| | 02:41 | So I have up here, on my screen, I have the
Eclipse Download page at eclipse.org/downloads/
| | 02:48 | and you'll notice all the way down here, it
says Eclipse IDE for C/C++ Developers and
| | 02:54 | I've already downloaded this Mac OS X 64 bit
version and I have that here in my Downloads folder.
| | 03:02 | So I have downloaded that from the Eclipse
website and I'm just going to double-click
| | 03:05 | on it here, and you see that the Archive
Utility expands it, and expands it again and then
| | 03:12 | we have this folder here
which is called eclipse.
| | 03:17 | And I simply drag this folder into my
Applications folder and over here in Applications, we see
| | 03:25 | there it is eclipse and I come in here and I
take Eclipse.app and I just drag that down
| | 03:31 | onto my doc here and I click
on it and that runs Eclipse.
| | 03:35 | It gives me a little warning that I
downloaded it from the Internet and I click Open and
| | 03:41 | now here it's just running because Java has
already been installed on this Mac, but if
| | 03:45 | Java had not been installed, it would
give me an opportunity to install Java.
| | 03:50 | It's giving me a default choice for my workspace
which is under Documents, under my user account.
| | 03:55 | I'm just going to say, Use this as default
and don't ask me again and say OK and there
| | 04:00 | we have the opening screen for Eclipse.
| | 04:03 | So I'm going to click the little green button
here to maximize this window and I'm going
| | 04:07 | to click on Workbench.
| | 04:08 | So you have a number of different choices here
and most of them are not things that we need.
| | 04:13 | We're just going to click on Workbench
and it'll default to this in the future.
| | 04:17 | And you notice over here at the right,
it's got my C/C++ tools highlighted.
| | 04:22 | You might have some other tools up here, you
might have some other things up here if you've
| | 04:26 | used Eclipse for other purposes.
| | 04:28 | But for our purposes, we're just
going to be using this C/C++ tools.
| | 04:32 | So this is our Eclipse workspace.
| | 04:34 | You might notice that it looks a little bit
different than the one that you have, and
| | 04:37 | you might notice it looks a little bit
different than the one that I used when I recorded the
| | 04:41 | rest of this course.
| | 04:42 | Different versions of Eclipse, they change
their interface a little bit now and then,
| | 04:46 | it shouldn't impact how you use
it. It will all work just fine.
| | 04:52 | So the first thing we're going to do is we're
going to open up the Preferences and so that's
| | 04:56 | under the Eclipse menu here and under
Preferences, or you can press Command+comma, like you
| | 05:00 | would with any Mac program.
| | 05:04 | Under General and Workspace, and you'll see
down here, Text file encoding and it defaults
| | 05:10 | to MacRoman, which is just wrong.
| | 05:13 | We want it to default instead to UTF-8
and we'll go ahead and press Apply.
| | 05:18 | The text file line delimiter,
Default is Unix, which is just fine.
| | 05:22 | If it doesn't say Unix there in yours, just click Other
and select Unix from these choices and click Apply.
| | 05:30 | Now we are going to come down here under C/C++
and New CDP Project Wizard, and you'll notice
| | 05:39 | that you have a selection here on the
left and a selection here on the right.
| | 05:42 | The selection on the left, Executable should
be opened up and if it's not, just open up
| | 05:46 | the little disclosure triangle there and select
Empty Project, and under Toolchains you want
| | 05:52 | to select the MaxOSX GCC Toolchain
and click Make toolchain(s) preferred.
| | 06:00 | Now we're going to come back up here to
General and under Editors and Text Editors, and we
| | 06:06 | just want to check everything here except for
Insert spaces for tabs and Show print margin.
| | 06:11 | So we're just going to check Show line numbers,
whitespace, all of these should be checked
| | 06:16 | except for Insert spaces for tabs and Show
print margin, everything else should be checked.
| | 06:21 | And under General and Appearance, you see
Colors and Fonts, and you probably don't need
| | 06:28 | to change anything in here, but I'm going
to come up here and under Basic and under
| | 06:33 | Text Font, I'm going to make it bigger because my
screen is going to show up really small on your screen.
| | 06:40 | And so, you probably do not need to change
this, I am just going to click Edit here,
| | 06:44 | so I'm going to go in here, and I'm just going
to type in 16 points and close that, and that's
| | 06:50 | just for my purposes of using this screen for the
training. You probably don't need to do that.
| | 06:57 | Now here under C/C++, under Editor, I'm
going to click on Folding and you want to check
| | 07:04 | all three of these boxes at the top and make
sure of all of these other ones are unchecked,
| | 07:09 | that enables all the different kinds of folding,
but initially does not use any of them and
| | 07:15 | that can be really useful.
| | 07:17 | So for now we're done here. We're going to come back
and we're going to change some of the stuff later.
| | 07:21 | I'm just going to press OK.
| | 07:23 | And we're going to now create a new project.
| | 07:27 | So under the File menu > New > Project,
do not select C++ Project for this, we'll
| | 07:35 | get to that later. For
now you want just Project.
| | 07:38 | These may be in a different order on your
menu and that's fine, just select the one
| | 07:41 | that says Project with the ellipsis after
it there, and under General you just want
| | 07:45 | to select Project, and again,
these may be in a different order.
| | 07:49 | You just want the generic
project at this point.
| | 07:51 | And we are going to select Next and we're going
to call this CppEssentialTraining, like that.
| | 08:01 | Do not use any spaces or any
punctuation in your file names in Eclipse.
| | 08:05 | They may be legal in your operating system,
they certainly are here on a Mac, but some
| | 08:10 | of these tools that are part of Eclipse are
actually pretty old and they get messed up
| | 08:14 | with spaces and
punctuation in your file names.
| | 08:17 | So I just avoid--when I'm using Eclipse, I avoid
using any spaces or punctuation in my file names.
| | 08:24 | And I'm just going to click Finish and now we have
this empty project here for C++ Essential Training.
| | 08:31 | I'm going to right-click on the project or
you can Ctrl+click if you have a one button
| | 08:35 | mouse and say New > Folder within the project.
| | 08:40 | And I'm going to click on this Advanced button
here and I'm going to say, Link to alternate
| | 08:45 | location for a Linked Folder, and we'll browse
here and on my Desktop, see my ExerciseFiles,
| | 08:54 | I'm just going to open that and
all this is now filled in for me.
| | 08:58 | The folder name is ExerciseFiles, it's
linked to an alternate location and there is the
| | 09:03 | exercise files I'm linked to.
| | 09:04 | So wherever you have your exercise files on
your system, I've got them on my desktop,
| | 09:09 | they may be someplace else in yours, you want
to link to that location and make sure you
| | 09:14 | have Link to alternate location selected
here and I am going to select Finish.
| | 09:19 | And so now when I open up this exercise files,
I see I have got each of my folders in here
| | 09:23 | and I open those up, they
have the files inside of them.
| | 09:27 | That's fine for now, now we are going to go
ahead and create a project that we're going
| | 09:30 | to use as our working space for
actually working on the files.
| | 09:34 | We are not going to work on them in place
here we are going to copy them into another
| | 09:37 | project where we are actually going
to compile them and work with them.
| | 09:40 | There is good reason for this and
we'll get to that a little bit later.
| | 09:43 | So we are going to come back up here to the
File menu and New and now we are going to
| | 09:48 | select C++ Project.
| | 09:51 | Our project will be called Working and you
noticed down here under Executable, it says
| | 09:57 | Empty Project and our Toolchain is MacOSX GCC.
| | 10:02 | So if any of these are not selected,
these may again be in a different order.
| | 10:06 | Executable may not be the one that's selected,
make sure you select Executable and Empty
| | 10:11 | Project under there, and your toolchain should
say MacOSX GCC and if it doesn't, you want
| | 10:17 | to go back and do this setup before that we
did in the Eclipse Preferences and make sure
| | 10:22 | that you set that for the default toolchain.
| | 10:25 | So I am going to select Finish here and it's
created a new project here called Working,
| | 10:31 | and you notice inside of it, it has an Includes
folder and that's all that's in it. So I come
| | 10:37 | up here to ExerciseFiles and open
Chapter 02 and select version-test.cpp.
| | 10:44 | And I'm going to copy that, I am pressing
Command+C on my keyboard and then select Working
| | 10:49 | down here, my Working project and select Command+V
on my keyboard to copy--to make a working copy
| | 10:55 | of that version-test.cpp.
| | 10:58 | If you just drag it down there, you run the
risk of moving the file rather than copying,
| | 11:03 | Eclipse ought to give you
the choice of copying it.
| | 11:05 | But it's a lot easier to just copy and
paste using Command+C and Command+V.
| | 11:10 | So now I am going to double-
click on version-test.cpp.
| | 11:14 | Now the first time you open this up, it may
show you some errors, it may take Eclipse
| | 11:20 | of couple of minutes even to update enough
of itself so that it recognizes this code,
| | 11:25 | and that's okay and that's not uncommon.
| | 11:29 | So the very first time that I run something
inside of Working I need to build, and so under
| | 11:34 | Project I am going to click Build Project,
and now it's done that and you will notice
| | 11:39 | down here in our Project we have a few extra
folders, we have his Binaries folder and we
| | 11:44 | have this Debug folder, and that's all to
be expected and that works just fine.
| | 11:48 | I am going to go ahead and collapse this panel
over there on the right so we have a little
| | 11:53 | more room for this.
| | 11:54 | I am just going to move this over here a
little bit, so we have a little more room for our
| | 11:58 | code, and now I am going to
go ahead and run the code.
| | 12:02 | On my Mac I can press Shift+Command+F11 or I can
press this green button up here that says Run.
| | 12:07 | And I am just going to run that, and now down
here at the bottom my Console becomes selected,
| | 12:15 | and I see the GCC version 4.2.1 and
my version string which says 4.2.1.
| | 12:21 | Now over here it says LLVM build and all
that means is this version of GCC was compiled
| | 12:29 | with the LLVM compiler. It does not
mean that this is based on LLVM at all.
| | 12:33 | And in fact, it's not. This is a very old version of GCC, as
of this recording this is a five-year-old version of GCC.
| | 12:41 | It is not sufficient for our purposes, so
we are not going to use it, instead we're
| | 12:47 | going to use the LLVM Compiler with
the C language front-end called Clang.
| | 12:53 | And so here's how we do this.
| | 12:54 | We come over here to our
Working project and select that.
| | 12:57 | I am going to press Command+I on my keyboard,
alternately you can right-click on it and
| | 13:02 | if you scroll all the way down here to the
bottom you will see something that says Properties,
| | 13:05 | and I am just going to press Command+I instead and
that brings up the Properties for the Working project.
| | 13:12 | Now if I come down here to the C/C++ Build,
and I open the disclosure triangle, and I click
| | 13:18 | on Settings down here, and you see where it
says MacOS X C++ Linker, GCC Assembler, GCC
| | 13:30 | C++ Compiler and GCC C Compiler.
| | 13:32 | So what we are going to do is we are actually
going to change these settings, so instead
| | 13:37 | of using the GCC Compiler, it's
going to use the LLVM Clang Compiler.
| | 13:42 | So we are going to start with the C++ one,
GCC C++ Compiler and up here where it says
| | 13:48 | g++ I am going to change it so that it says c++,
and then in that same section under Miscellaneous,
| | 13:54 | I am going to add a couple of command line
options down here, so I put in a space and
| | 14:00 | I type -std=c++11.
| | 14:05 | That tells it to use the C++11 standard for
its internal compiler, and another space and
| | 14:11 | -stdlib=libc++, that tells it to use the
Apple version of the libc++ standard library.
| | 14:24 | And up here under the MacOS X C++ Linker,
I do the same thing, I change that g++ to
| | 14:32 | say c++ and then under Miscellaneous down
here, I add -stdlib=libc++; exactly the same
| | 14:42 | as I did for the C++ Compiler.
| | 14:45 | Now we come over here under the C Compiler
and I change GCC to just CC like that, and
| | 14:52 | under Miscellaneous, I am going to come out
here and I am going to say space -std=gnu11
| | 15:01 | and that will have it use the latest
standard for C programs as well as C++ programs.
| | 15:08 | Now there is just one more thing we need to
do here, under Run/Debug Settings over here
| | 15:12 | on the left, select our Working project and press
the Edit button, and come over here under Arguments.
| | 15:19 | We are going to going to give it some default
arguments so that every time it runs our Working
| | 15:23 | project it's going to run it with some command
line arguments. So we are just going to type
| | 15:26 | in the words one two and three, and those will
be used for our command line arguments whenever
| | 15:32 | we run that project.
| | 15:33 | So we say OK there, over here we say Apply
and OK, and now I'm going to come back over
| | 15:41 | here under Project and I'm going to run
Clean, and I am going to make sure it says Clean
| | 15:46 | all projects and just say OK, and
now we are going to run it again.
| | 15:50 | We are just going to press this Run
button and it will compile it and run it.
| | 15:55 | And now you see it says Version string, it still says
4.2.1, but it says here 4.2.1 Compatible Apple Clang 4.1.
| | 16:05 | This is a different compiler that one we were
running before. This is actually now using
| | 16:09 | Apple Clang 4.1 with the LLVM Compiler, and
we can test this and make sure that it uses
| | 16:17 | our updated C++11 features by
uncommenting this block of code.
| | 16:22 | I am just going to select it and I am going
to press Command+/ on my keyboard which will
| | 16:27 | uncomment it, and Command+S to save and press the
Run button up here, the little green Run button.
| | 16:33 | And now you will notice that it's actually
running all this code and we have the one two three.
| | 16:38 | So these are C++11 features.
| | 16:40 | This is the initializer list,
this is the range based for loop.
| | 16:44 | These will not work in that old
version of GCC that we were using before.
| | 16:49 | So we are actually now compiling
successfully with the Apple Clang LLVM Compiler.
| | 16:56 | Now just one more test we want to run here.
| | 16:58 | I am going to go ahead and I'm going to run
Project > Clean and that will clean our project.
| | 17:03 | I'm going to delete this file from our
Working project; I am just pressing the Delete key
| | 17:08 | here on my Mac keyboard and the
Enter key to select OK there.
| | 17:13 | Now I am going to come up and make a copy
of this c99.c out of the Chapter 02 folder
| | 17:19 | of our exercise files, so I am pressing Command+C,
come down here to the Working project, Command+V,
| | 17:24 | double-click on it and compile and run.
| | 17:27 | Just press this green button, it compiles
it and runs it and we'll notice here that
| | 17:33 | it's running this code just fine.
| | 17:34 | Now, this is using code in the C language
that will not work with that older compiler.
| | 17:40 | In particular, this declaring and
initializing a variable inside of a for loop, this is a
| | 17:46 | C99 future and with the default installation
of the GCC Compiler, there are command line
| | 17:51 | switches that you can give it that will make
this work, but this is showing that we have
| | 17:55 | done that installation properly and
that everything is working as it should.
| | 17:59 | So we'll go ahead and run a Clean again from
our Project menu, and we'll delete this file
| | 18:04 | from our Working project, and now we have a
working Eclipse with the latest LLVM Clang
| | 18:10 | Compiler installed and running on a Mac.
| | 18:12 | Again, there is no reason that you need to
run Eclipse, but if you don't have another
| | 18:16 | environment or you would like to just follow
along with the exercises in this course, Eclipse
| | 18:20 | will work just fine for you.
| | Collapse this transcript |
| Setting up Eclipse with GCC on a Mac| 00:00 | In this movie, we're going to install
the Eclipse C Development Tools on a Mac.
| | 00:05 | Keep in mind that it is not necessary
to install Eclipse in order to take this
| | 00:09 | course, you may use whatever
development environment you like, in fact I
| | 00:13 | encourage you to use your
own development environment.
| | 00:16 | I am using Eclipse for the examples in this
course, because it's convenient for this purpose.
| | 00:21 | It allows me to demonstrate the
examples in a way that's accessible to students
| | 00:25 | on any of the three major platforms today;
Windows, Mac and Linux.
| | 00:29 | That is the only reason I'm
using Eclipse for this course.
| | 00:32 | I normally do my development work
with whatever tools are supported on the
| | 00:36 | platform I am working on, and
I encourage you to do the same.
| | 00:40 | In order to install Eclipse on
a Mac, you'll need a few things.
| | 00:43 | You'll need a relatively modern Mac running
Xcode with the Command Line Tools installed.
| | 00:48 | You'll need the Java Runtime Environment,
and you'll need a version of the GNU
| | 00:52 | compiler, GCC version 4.70 or later.
Let's take a look at these, one at a time.
| | 01:00 | I have Xcode running here on this Mac,
and I have the Preferences dialog box
| | 01:04 | open, and I've selected
Downloads in the Preferences.
| | 01:08 | And you'll notice the bottom item here, it
says Command Line Tools, and it says Installed.
| | 01:13 | If yours does not say Installed, it
will have one of these Install buttons
| | 01:17 | like this other stuff has, and you'll
press that button, and you'll install
| | 01:21 | the Command Line Tools.
| | 01:22 | Keep in mind that in order to install
the Command Line Tools on a Mac, you'll
| | 01:26 | need an Apple Developer account.
| | 01:28 | The free version of the Apple
Developer account is just fine.
| | 01:32 | So I am just going to quit out of Xcode
here, I am going to press Command+Q, and
| | 01:37 | now we are going to install Eclipse.
| | 01:38 | Now Eclipse is written in Java, and it
was originally developed to be a Java
| | 01:43 | IDE, IDE stands for
Integrated Developer Environment.
| | 01:47 | And over the years it's been
expanded to support a number of different
| | 01:50 | languages, and it now also supports C and C++.
| | 01:54 | The beauty of Eclipse is that the same code
runs on a number of different platforms.
| | 01:59 | So I can demonstrate for you the
examples for this course, and you can have
| | 02:03 | exactly the same screen on your
screen and follow along no matter what
| | 02:06 | platform you're running;
Windows, Mac or Linux.
| | 02:10 | But you do need a Java Runtime
Environment in order to run Eclipse.
| | 02:14 | The nice thing on a Mac is the first
time you run Eclipse, if you don't have
| | 02:17 | Java installed, it will give you the
opportunity to install it at that time.
| | 02:21 | So looking down here, you see it says Eclipse IDE
for C/C++ Developers (includes Incubating components).
| | 02:29 | And if yours doesn't say that includes
Incubating components, that's just fine.
| | 02:32 | That just means some of the
components that are included are yet
| | 02:35 | considered fully released in the
Eclipse world, but they're working just
| | 02:39 | fine for our purposes.
| | 02:41 | So because it knows that I am on a Mac,
you've got this little drop box here if
| | 02:44 | you want to install something else,
but it should default to Mac Cocoa.
| | 02:48 | And you see I have a choice
of the 64 Bit or the 32 Bit.
| | 02:52 | This is a 64 Bit Mac and so
I've downloaded the 64 Bit version.
| | 02:56 | And you can see it right here
in my Finder under Downloads.
| | 02:59 | So I am just going to double-click on
that eclipse-cpp blah, blah, blah...
| | 03:03 | And you'll go ahead and expand the
archive, and I have this folder called
| | 03:07 | eclipse, and I am just going to drag
that into Applications and eclipse, believe
| | 03:11 | it or not is now installed.
| | 03:13 | So I'll select Applications, and I'll
scroll down here until I find eclipse, and
| | 03:18 | there is the folder, and inside
the folder, I have Eclipse.app.
| | 03:22 | I am just going to drag that
down here to my dock and run it.
| | 03:26 | It says I've downloaded it from the
Internet, and I am sure that I want to run
| | 03:30 | that, so I select Open, and there it is.
| | 03:33 | Now at this point, if you didn't have
Java installed, it would give you the
| | 03:37 | opportunity to download and install Java.
| | 03:39 | So the first time I run Eclipse,
there's a number of things I have to do.
| | 03:42 | The first one is is I
have to select a workspace.
| | 03:45 | So there is what it's defaulted for
me, and I am just going to accept the
| | 03:48 | default, and I'm just going to click
this box so that it doesn't ask me every
| | 03:51 | time I start up Eclipse.
| | 03:54 | Now it's finished loading the rest of
its stuff, and I'm just going to click
| | 03:58 | on Workbench which is the rightmost button
here, and that will take me to my Workbench.
| | 04:03 | And I am going to click
Maximize, and there we have Eclipse.
| | 04:06 | So the first thing I am going to do
before I create a Workspace is I am going to
| | 04:10 | set some preferences here.
| | 04:12 | So come up here into the Eclipse menu
and select Preferences and under General,
| | 04:17 | go down here to Workspace, and you
see where it says Text file encoding.
| | 04:22 | The Default is MacRoman, MacRoman is a
very, very old text file encoding, and we
| | 04:27 | are not going to be using that,
we are going to be using UTF-8.
| | 04:30 | So I select Other in the dropdown box,
and I select UTF-8, and that allows us to
| | 04:37 | work with files from different platforms.
| | 04:39 | Of course all the files in the exercise
files are in UTF-8 so that they'll work
| | 04:43 | on different platforms.
| | 04:45 | So I am going to press Apply, and then
I'm going to go up here to General and
| | 04:49 | Editors and under Text Editors, I am
going to select a bunch of these boxes.
| | 04:55 | I am actually going to select all of
the check boxes except Insert spaces for
| | 04:59 | tabs and Show print margin.
| | 05:01 | So I am going to select line numbers,
range indicator, whitespace characters,
| | 05:06 | of course Highlight current line, all of these
are going to be selected except for those two.
| | 05:12 | I am also going to click on this
little link down here that says Colors and
| | 05:15 | Fonts, you can also find that under
Appearance > Colors and Fonts, and this is
| | 05:20 | just for the purposes of my
computer while I am demonstrating.
| | 05:24 | I need to make the text a little bit
larger than the default, you probably
| | 05:28 | don't need to do that.
| | 05:29 | If you select this, and you look down
here, and you can read The quick brown
| | 05:33 | fox, and it looks just fine to you,
then you don't need to change this.
| | 05:37 | For my purposes I need to
use a little bit larger font.
| | 05:40 | So I am going to select that and
press Edit and under my Recently Used I
| | 05:44 | have this Calynda and 18 point,
and that makes this nice and big and
| | 05:50 | readable for this purpose.
| | 05:52 | I am also going to do the same thing
under Text editor Block Selection Font.
| | 05:55 | That probably won't even get used,
but just in case there it is.
| | 06:00 | Now we are going to go here under C/C
++, I am going to fold up this General
| | 06:04 | here and go under C/C++.
| | 06:06 | And under New CDT Project Wizard you
have Preferred Toolchains selected here and
| | 06:12 | Empty Project under Executable, and
I am going to select the MacOSX GCC.
| | 06:18 | For the Toolchain, I am going
to say Make toolchain preferred.
| | 06:21 | And you see you get that little
arrow there next to the MacOSX GCC.
| | 06:25 | And that's really important, that
makes the MacOSX GCC toolchain the default
| | 06:30 | toolchain for all of your new projects.
| | 06:33 | If that's not selected, your new
projects won't compile and they won't run.
| | 06:37 | Still under C/C++ here, I am going to
go to editor, and I am going to expand
| | 06:42 | that, and I am going to click on Folding.
| | 06:45 | What Folding is is that's when you have
blocks of things in your source code, it
| | 06:49 | can fold them up so that you don't
see all of the contents of that block.
| | 06:53 | We want that enabled, but
we want it off by default.
| | 06:58 | So we are going to select all of
these enabled things, and we are going to
| | 06:59 | uncheck all of these initially fold things.
| | 07:02 | So your screen should look like this,
you got the top three checked and all of
| | 07:06 | these other ones, unchecked.
| | 07:08 | So I am going to press Apply, and I am
going to press OK, and we're now ready
| | 07:12 | to create a project.
| | 07:13 | So I am going to go in here to Project
Explorer, and I'm just going to select
| | 07:16 | this little disclosure triangle there
next to the New project icon, and I am
| | 07:21 | going to say Project, the generic project.
| | 07:23 | We're not making a C++ Project at this
point, we're making a generic project
| | 07:28 | because this is just going to be a
holding tank for our source files, we're not
| | 07:32 | actually going to compile inside this project;
| | 07:34 | we are going to create a second
project for doing our compiling.
| | 07:37 | So I'll select that and under General,
I am going to select Project, and I am
| | 07:42 | going to press Next.
| | 07:43 | I am going to name the Project C++ (Cpp
), and I'm just using the P characters,
| | 07:48 | and I am going to say EssentialTraining, and
you'll notice I don't even have any spaces.
| | 07:53 | I don't typically like to use spaces in
file names especially for source code,
| | 07:58 | because there are some tools
occasionally that seem to not work with spaces and
| | 08:02 | special characters in filenames, so for
the most part, I really try to stick to
| | 08:06 | just plain ASCII compatible text
characters in filenames, and that avoids
| | 08:11 | problems that can sometimes be hard to find.
| | 08:14 | So I am just naming it
CppEssentialTraining like that.
| | 08:17 | And I am going to select Finish, default
location is fine for me, you might want
| | 08:21 | to put it someplace else. But that's fine.
| | 08:23 | And I am going to right-click on that
and say New > Folder and select Advanced,
| | 08:30 | and we are going to link
to an alternate location.
| | 08:33 | This allows us to bring in our
exercise files without actually having to move
| | 08:37 | them from their default location,
because we are not going to really edit them
| | 08:41 | in place, we're going to be making
copies of them and putting them into our
| | 08:45 | Working project in order to compile them.
| | 08:47 | So press Browse and--on the Desktop--
select ExerciseFiles, that's where I've put
| | 08:54 | my ExerciseFiles, yours may be someplace
else, and Open, and it will fill in the
| | 09:00 | folder name, you can leave that alone
and the rest of this should be just fine,
| | 09:04 | and I can say Finish.
And there we have it.
| | 09:06 | Now we have our project with our
ExerciseFiles, and you see there are all of the
| | 09:11 | ExerciseFile folders
inside with all of those files.
| | 09:15 | For now, I am going to come back up
here and make one more project, and this is
| | 09:20 | actually going to be a C++ Project.
| | 09:22 | We are going to call this one working,
Use default location is fine, you
| | 09:26 | notice the Toolchain is selected, it says
MacOSX GCC, and it's got the little arrow next to it.
| | 09:32 | If yours doesn't have that little
arrow then you need to go back and do
| | 09:35 | the Preferences setting again, because you
missed something in setting the Preferences.
| | 09:40 | So you leave this as Empty Project and
make sure that that's selected and just
| | 09:46 | press finish, and we now have our
Working project down here, and you'll notice
| | 09:50 | that it just has one folder inside of
it for the Includes, we're going to a
| | 09:54 | fix that in a moment.
| | 09:55 | First thing I am going to do here is I
am going to go under ExerciseFiles in
| | 09:58 | the CppEssentialTraining and select Chap02, and
there's a file in here called version-test.cpp.
| | 10:06 | If you want to make copy of that, you
can press Command+C or you can Ctrl-click
| | 10:10 | or right-click and select Copy and
then come down here to Working and either
| | 10:14 | press Command+V or Ctrl or
right-click and press Paste.
| | 10:18 | So what we've done is we've copied and
pasted this file here down into Working,
| | 10:22 | and that's how we're going to run
all of our examples in this course.
| | 10:26 | So that's the pattern you
are going to get used to.
| | 10:28 | You select the file in the exercise
files, press Command+C to copy it and come
| | 10:32 | down here to Working and Command+V to paste it.
| | 10:35 | Now before we can run it, we
need to actually select the project.
| | 10:39 | So I am selecting the word Working there,
and it's highlighted and then come up
| | 10:44 | here to Project and select Build All or
just press Command+B. And you'll notice
| | 10:49 | that what this does is it builds up
the project, and it builds all of the
| | 10:53 | support files inside of the project
that it needs and creates a couple of extra
| | 10:57 | directories and everything, and it
actually compiles stuff and makes stuff all
| | 11:01 | ready so that it will work.
| | 11:03 | You only need to do that the
first time you create the project.
| | 11:06 | We won't actually need to do that
anymore throughout the rest of the course.
| | 11:10 | So I am going to double-click on version-
test.cpp, and there is our source code
| | 11:14 | in nice big letters, yours hopefully
will be the right size for you, and I am
| | 11:19 | just going to double-click on this
here so that you can see the entire file.
| | 11:23 | There's a lot of stuff in here that you
don't need to understand at this point.
| | 11:26 | Really all we're doing right now is
trying to find out what version of
| | 11:30 | compiler we have installed.
| | 11:31 | But I want to show you a few things here
at this point, because as we go through
| | 11:35 | the course you're going to notice these things.
| | 11:36 | First of all, you'll notice that all of
the spaces are visible as little middle
| | 11:40 | dots and they are light color gray, the
tabs look like this with the two right
| | 11:47 | angle bracket character, it's like a
European quote mark and the paragraph
| | 11:51 | markers look like that.
| | 11:53 | And the purpose of this is whenever I'm
working with source code, these little
| | 11:57 | details like is that a space character
or is that a tab character, these things
| | 12:01 | can sometimes matter.
| | 12:02 | So whenever I am working with source
code, my Text editor always has all of the
| | 12:06 | meta-characters visible, whatever they
call it, whitespace characters or show
| | 12:10 | tabs and spaces or whatever that
setting is in the editor that I am working
| | 12:14 | with, that stuff is always visible.
| | 12:16 | So here is our source file, and I'm
going to go ahead and compile and run it,
| | 12:20 | and select from the Run
menu, this Run Last Launched.
| | 12:23 | Actually, I am not even going to
do that, I am just going to press
| | 12:26 | Shift+Command+F11, because you are
going to want to know a shortcut for this,
| | 12:30 | you are not going to want to have to
go to the menus all the time for it.
| | 12:33 | Alternately, you can come up here and
press this little green arrow, and that
| | 12:36 | will do the same thing.
| | 12:37 | So I am just going to press Shift+F11
and F, and it compiles it, and it runs it,
| | 12:43 | and there we have the console right up
here, and it says GCC version 4.2.1, and
| | 12:48 | it's got this version string that
this is the Apple default compiler.
| | 12:52 | And if I close that and come back up
here and double-click on that tab, and then
| | 12:57 | we have our full screen, this is
probably the way you'll run things.
| | 13:00 | And if I do this again, Command+
Shift+F11, and it runs it down here.
| | 13:05 | So you can see the source code
and the output at the same time.
| | 13:09 | It might also be worthwhile for you to
know that if you press this icon over
| | 13:13 | here, it says Display Selected Console;
| | 13:17 | you can see the output of the compiler as well.
| | 13:20 | Then press it again, and you get the
output of the program after its run.
| | 13:24 | So what we know at this point is that we
are running GCC 4.2.1, and that is less
| | 13:30 | than 4.7.0, which is the minimum we
need to be able to use C++11 features, and
| | 13:36 | so at this point, we actually need to
download and install the latest GCC.
| | 13:42 | And I'll show you how to
do that in the next movie.
| | Collapse this transcript |
| Upgrading GCC on a Mac| 00:00 | In this movie we are going to upgrade the
GCC toolchain for use with Eclipse on a Mac.
| | 00:06 | Here I have Eclipse installed on this
Mac, and I've found that the GCC version
| | 00:10 | is not sufficient to support
the latest C++ Standard C++11.
| | 00:15 | You notice here that the GCC version
is 4.2.1, and this class uses C++11
| | 00:21 | features, so we'll need a GCC of at
least 4.7.0 for its C++11 support.
| | 00:28 | As of the time that I am recording C++11
is new and GCC 4.7 is new, so we are
| | 00:35 | going to install 4.7.0 so that it
has support for the new C++ features.
| | 00:40 | Here I have the web page of High
Performance Computing, which is a port of GCC
| | 00:46 | that works on a Mac.
| | 00:48 | And it's hosted at sourceforge.net
and the URL is hpc.sourceforge.net.
| | 00:55 | And we'll see here that the latest
version is GCC 4.7, and you're free to
| | 01:00 | use the latest version whatever that is,
and you'll notice under binaries we
| | 01:04 | see gcc-lion.tar.gz.
| | 01:07 | There's another one gfortran-lion.tar.gz, and
that's only FORTRAN that does not include C++.
| | 01:15 | There's also versions down here for
Snow Leopard, so if you're running
| | 01:19 | Snow Leopard, and you're not
running Lion, then you'll want to install
| | 01:23 | that Snow Leopard version.
| | 01:24 | I am running Lion on this Mac and so
I've already downloaded gcc-lion, and I
| | 01:30 | have that here in my Downloads folder.
| | 01:33 | I am just going to double-click on it
and let OS X open the Archive and here we
| | 01:39 | have a folder that includes the compiler tools.
| | 01:42 | And so under this usr and under local
you see there are our compiler tools.
| | 01:47 | We have bin, include, lib, libexec, and share.
So that's all the GCC toolchain.
| | 01:54 | So I am going to take this local folder,
and I'm actually going to rename it,
| | 01:58 | and I'm going to call it hpc-gcc.
| | 02:03 | And you want to do that with the local folder,
you don't want to rename the user folder.
| | 02:07 | And I am just going to drag
it into my home directory.
| | 02:10 | And there it is it's going to be
whatever your home directory is on your Mac.
| | 02:14 | So you drag it into your home folder,
and there I've selected my home folder,
| | 02:18 | and you see I have a folder there
called hpc-gcc, and when I click on it it's
| | 02:22 | got that bin, include, lib, libexec,
all of those folders inside of it.
| | 02:27 | So it's real important that it'd be
named that, and it'd be there, because we're
| | 02:31 | going to use that location as we
set the preferences in Eclipse.
| | 02:34 | Now I am going to go back over here to
my Downloads folder, and I am just going
| | 02:38 | to delete this usr folder.
| | 02:40 | And now I am going to come back into
Eclipse, and then I am going to select my
| | 02:44 | Working project and right-
click and select Properties.
| | 02:48 | So this is setting the
properties of the Working project.
| | 02:52 | You see it says Properties for Working.
| | 02:53 | This is not the properties for
the entire Eclipse application.
| | 02:57 | So under C++ Build here, C/C++
Build, you'll notice something called
| | 03:03 | Environment, and here in the
Environment we're going to add a few
| | 03:07 | Environment variables, and this
will tell Eclipse where to find the
| | 03:10 | toolchain so that it will use the
correct version of GCC and leave the
| | 03:15 | version alone that Xcode wants.
| | 03:17 | Because Xcode still depends on that, it
still needs to be there for your Xcode to work.
| | 03:22 | You can't delete it, you're still going to be
depending on the other tools that Xcode has;
| | 03:26 | you need to leave Xcode alone.
| | 03:28 | And yet we've installed this other
version of GCC in our home directory, and we
| | 03:32 | want to use that for compiling in Eclipse.
| | 03:35 | Under Configuration I am going to
select All configurations, and then I am
| | 03:40 | going to select Add.
| | 03:41 | I am going to type CPATH and then under Value I am going
to put a dollar sign $ and a left curly bracket and the
| | 03:49 | word HOME, all in caps, and a right curly bracket.
| | 03:53 | Instead you can select Variables, and
you can come down here, and you can find
| | 03:57 | HOME and click on it and press
OK, and you get the same thing.
| | 04:02 | That tells it that it's under my home
directory whatever that's called and in my
| | 04:05 | case it's that
billweinman directory that we saw.
| | 04:08 | And I am going to press slash and hpc-
gcc because that's what we named the
| | 04:14 | folder and then another slash and include.
| | 04:17 | Now if you're not familiar with file
name paths in UNIX or in OS X, these are
| | 04:24 | forward slashes, these are not backslashes.
| | 04:26 | These are just the slash key which
is right next to the Shift key on your
| | 04:30 | keyboard without Shift
pressed or anything like that.
| | 04:32 | Now I'll press OK, and I am
going to do a couple more of these.
| | 04:37 | The next one is called LIBRARY_PATH,
and you'll notice that there is
| | 04:41 | an underscore there.
| | 04:42 | LIBRARY_PATH, and I am going to select
Variables again grab that HOME variable,
| | 04:47 | and there it is and press
/hpc-gcc/lib and press OK.
| | 04:58 | So we have LIBRARY_PATH
set, and we have CPATH set.
| | 05:03 | Now we're going to set one more, this is
the Path variable, and this one has got
| | 05:06 | a little bit of rigmarole to it.
| | 05:08 | So here's how it goes, it's called PATH,
and there's already a path variable
| | 05:13 | set, although it doesn't show up there.
| | 05:16 | After we set it we are going to notice
that what we put here gets added to the
| | 05:20 | end, we're going to need to come
back in and edit it and move it to the
| | 05:22 | beginning, because it
needs to be at the beginning.
| | 05:25 | So I am going to go here under Value,
and I am going to select Variables
| | 05:28 | again, and I am going to find our little HOME
and double-click on that and say /hpc-gcc/bin.
| | 05:40 | Now when I say OK you'll notice that we
look at what path has, and it's all this
| | 05:44 | other stuff, and if I press Edit over
here you'll see that what I added actually
| | 05:48 | went all the way to the end of the variable.
| | 05:51 | So I need to select that, I am holding down
the Shift key and pressing the left arrow.
| | 05:55 | I press the right arrow to get to the
end, and I am holding down the Shift key
| | 05:58 | and pressing the left arrow, and I am
coming all the way back here, and I'm
| | 06:02 | taking the colon as well.
| | 06:04 | You'll notice there's a colon at the end of sbin
and then there's the $ curly brace HOME curly brace.
| | 06:08 | So I am taking that colon as well, and
I am pressing Command+X to cut, because
| | 06:13 | then I am going to paste.
| | 06:15 | And I press the up arrow, and that will
take me to the beginning, and I am going
| | 06:19 | to press a colon and then my left
arrow to go before the colon, and then I am
| | 06:23 | going to press Command+V to paste.
| | 06:25 | And then I need to go all the way
back to the beginning and take that
| | 06:27 | first colon out again.
| | 06:28 | So I'll select that and hit the
Delete key, and now what we have is we have
| | 06:33 | $ curly brace HOME curly brace/hpc-gcc/bin and then there
is a colon and then the other stuff that
| | 06:43 | was already in the variable
starting with the /usr/sbin.
| | 06:47 | It's really important that it
look like this, that it has this
| | 06:51 | HOME hpc-gcc/bin at the beginning
and not at the end of the variable.
| | 06:56 | So I am going to press OK, and we see
that we have that correct right there.
| | 07:00 | Now I am going to press the Apply
button over here, and that applies it.
| | 07:04 | Now I am going to go back over here to C/
C++ Build an then down here to Settings.
| | 07:09 | So under Settings you see we have tool
Settings selected at the left here and
| | 07:12 | these are settings for all of our tools.
| | 07:14 | And we have the C++ Linker, the GCC
Assembler, and we have the C++ Compiler, and
| | 07:20 | the C Complier and those are the
ones that we are interested in.
| | 07:24 | If I select the GCC C++ Compiler,
you'll notice that it has all of these
| | 07:29 | options down there.
| | 07:30 | And if I come down here to
Miscellaneous I am going to add an option here.
| | 07:35 | I am going to put in a space at the end of
this list of options, and I am going to say -std--
| | 07:41 | it's an abbreviation for the word
standard-- = c++11, so two 1s.
| | 07:48 | So it is letters c, two +
symbols and two number 1s. -std=c++11.
| | 07:56 | Now you'll notice if I come back up
here and click on GCC C++ Compiler you'll
| | 08:01 | see that there is that option at the
end so that's what I wanted to accomplish.
| | 08:05 | You can't edit that here, you need
to edit that under Miscellaneous.
| | 08:08 | I am going to do the same
thing under the C Complier.
| | 08:11 | So this is GCC C Compiler, and you'll
notice that all of the options are there.
| | 08:16 | If I come down here under
Miscellaneous, I am going to add the options for
| | 08:20 | latest version of the C
standard which is also C11.
| | 08:24 | So this is -std=gnu11.
| | 08:30 | So that's the C11
standard with the gnu extensions.
| | 08:34 | So there is one more thing we need to do here.
We need to go in here to the Run/Debug Settings.
| | 08:40 | And that's right over here under C++
General down here Run/Debug Settings
| | 08:45 | and our Launch configuration for
our Working project we are going to go
| | 08:50 | ahead and edit that.
| | 08:51 | So I select Working, and I press Edit,
and I come in here, and there is a couple
| | 08:55 | of things we want to do.
| | 08:56 | One, I want to come over here to
Arguments, and I just want to put in some
| | 09:01 | arguments because we'll use these occasionally.
| | 09:02 | So under our Program arguments I am
going to type the words for one two three,
| | 09:07 | like that, and it's just as if you run
something at the command-line, and it's
| | 09:10 | got three arguments after it.
| | 09:12 | So it's like you type your command,
and then you type a one, and a two, and a
| | 09:15 | three on the command-line,
that provides it that environment.
| | 09:19 | Then I am going to select the Environment tab,
and we are going to add Environment variable.
| | 09:24 | Because we are running a C
Compiler that's not the default C Compiler
| | 09:27 | that's installed in the operating
system, we need to tell it where to find
| | 09:31 | its libraries, because it's not going to
find the right libraries in the normal place.
| | 09:35 | In fact, it will find libraries in the
normal place, but they'll be the wrong libraries.
| | 09:40 | So we want to make sure that
it finds the right libraries.
| | 09:42 | So we just have to add a
variable to the environment here.
| | 09:45 | This is for the runtime environment.
| | 09:47 | The other variables that we added before,
those were for the compile time environment.
| | 09:50 | These are for the runtime environment.
| | 09:52 | I have Environment selected, and I am
going to press New, and I am going to name
| | 09:57 | this variable DYLD_LIBRARY_PATH.
| | 10:04 | And if I select variables here I'll find
one called env_var, because there isn't
| | 10:09 | one that's called HOME.
| | 10:11 | And under Argument I am going to
type the word HOME all in caps.
| | 10:15 | Press OK, and I get this env_var:HOME thing
like that, and that's exactly what you want.
| | 10:21 | So if you have that, great.
| | 10:23 | If not, you can just type it here, and
it will work just fine. And /hpc-gcc/lib.
| | 10:31 | I am going to say OK, and there we
have DYLD_LIBRARY_PATH and the value.
| | 10:37 | So I am going to press the OK button
and press the OK button again and at this
| | 10:43 | point we should have the correct
version of our Compiler installed.
| | 10:47 | So I can just come up here, and I can
press the Run Working button, and it will
| | 10:51 | rebuild it, and there is GCC version 4.7.0,
Version string 4.7.0. We now have a
| | 11:00 | sufficient version of GCC.
| | 11:01 | If you're doing this at some point in the
future you may have a later version of GCC.
| | 11:06 | As long as it's 4.7.0 or
later you should be fine.
| | 11:10 | We are going to do one more thing to test this.
| | 11:12 | I am going to go ahead and put this in
fullscreen mode so you can see this entire file.
| | 11:16 | And I am going to select all of this stuff here.
| | 11:18 | This only works in C++11, and I am going
to uncomment it by pressing Command+/ key.
| | 11:25 | And that's just a little shortcut
inside of Eclipse that takes those comment
| | 11:28 | markers out from the beginning.
So now it should look like this.
| | 11:31 | And I am going to press Command+S to
save, and I am going to minimize it again
| | 11:36 | by double tapping on the title
there, and I am going to press Run.
| | 11:41 | Now you will see it also says one two three.
| | 11:43 | So what it did, I am going to maximize
this again so you can see it is it came
| | 11:48 | out here, and it creates a C++
vector which is like an array.
| | 11:53 | And it uses this feature here, the for
each version of the for loop, which is
| | 11:57 | not a C construct that existed before C++11.
| | 12:01 | It's also using this initializer
list which is another C++11 feature.
| | 12:05 | So it's using some C++11
feature, and it is working.
| | 12:09 | Now one final thing I am going to do
here is I am going to go ahead and I'm
| | 12:14 | going to delete this file so that we are in a
nice working state as we start our next exercise.
| | 12:18 | And I am just going to select it and
press the Delete key here on my Mac
| | 12:21 | keyboard or you can just right-click and
select Delete, and I am going to say OK.
| | 12:26 | And because we were using a copy we
still have it up here in the Chap02 folder, but
| | 12:30 | it's now deleted from our Working project.
| | 12:33 | So in using Eclipse in this course we
have the C++ Essential Training project,
| | 12:38 | and that's just holding all the exercise files.
| | 12:41 | When we want to actually use an
Exercise File, we select that, we copy it, we
| | 12:45 | paste it into Working, and we use it down there.
| | 12:47 | So now you have working Eclipse with the
latest GCC installed and running on your Mac.
| | Collapse this transcript |
| Setting up Eclipse for Windows| 00:00 | In this movie, we are going to
install the Eclipse C Development Tools on a
| | 00:04 | PC running Windows 7.
| | 00:06 | Now, it's not necessary to install
Eclipse in order to take this course.
| | 00:11 | You may use whatever
development environment you like.
| | 00:13 | In fact, I encourage you to use
your own development environment.
| | 00:16 | I am using Eclipse for the examples in this
course because it's convenient for this purpose.
| | 00:21 | It allows me to demonstrate the
examples in a way that's accessible to students
| | 00:25 | on any of the three major platforms today;
| | 00:27 | Windows, Mac, and Linux.
| | 00:29 | That is the only reason I'm
using Eclipse for this course.
| | 00:32 | I normally do my development work
with whatever tools are supported on the
| | 00:36 | platform I'm working on, and I
encourage you to do the same.
| | 00:39 | Now, in order to install
Eclipse, you will need three things;
| | 00:43 | you need the Java Runtime
Environment, you'll need the GNU GCC Compiler
| | 00:48 | version 4.7 or later, and you will
need Eclipse with the CDT, that's the C
| | 00:54 | Development Tools, and you will need
the version that's appropriate for your
| | 00:58 | PC and your Java installation.
| | 01:00 | So the first thing we're going to do
here is we are going to go to the Java website,
| | 01:04 | and we are going to check and
make sure we have Java on this machine.
| | 01:07 | I am going to click on Do I have Java?
| | 01:09 | And verify Java version, and it says
that I have the recommended latest Java
| | 01:14 | version installed on this machine.
| | 01:16 | If I did not have that, it would give me
the opportunity to download and install that.
| | 01:20 | So we have Java on this machine.
| | 01:22 | The next thing we need to do is
make sure we have the proper compiler.
| | 01:26 | Now, there is a number of ways to
download and install the GCC Complier, and
| | 01:31 | I've found one that works, that
has this latest version of GCC, that
| | 01:36 | supports C++11 and C11.
| | 01:39 | So, both the C language and the C++
language have recently had major releases
| | 01:44 | and the only compiler that I am aware of
at this time that supports these latest
| | 01:49 | versions is the latest version of GCC.
| | 01:51 | The latest version of the normal tools
for installing GCC on a PC which is the
| | 01:57 | MinGW environment does not
have that latest version of GCC.
| | 02:02 | So, there's this company here called
Equation Solution which has created a
| | 02:07 | version of MinGW that has
the latest version of GCC.
| | 02:12 | So, long story short, you come in here
to this web site, you go to Programming
| | 02:16 | Tools, and you go to Fortran, C, C++,
and you'll see it down here, and whatever
| | 02:22 | version is there, may or may not work.
| | 02:24 | So, what I've done for you is I have
downloaded this and put it in the exercise files.
| | 02:30 | So, if you look in the exercise
files, and I am going to switch to the
| | 02:32 | desktop here and open the exercise files,
you'll see this folder, it says WindowsSupport.
| | 02:38 | Under WindowsSupport, you will see gcc-4.7.0;
| | 02:40 | you have a 32-bit version and a 64-bit version.
| | 02:44 | If you don't already have installed
a later version of GCC that works in
| | 02:49 | whatever environment it is that
you're using just use this one.
| | 02:52 | This one works, it's tested, and I know
that it works with Eclipse and everything.
| | 02:57 | So I have already copied this to my
Downloads folder along with Eclipse, and
| | 03:02 | let's go ahead and see where you get Eclipse.
| | 03:04 | You should use the latest version of
Eclipse if it's available, and so here we
| | 03:08 | have the eclipse.org web site under Downloads.
| | 03:10 | And if you look down here Eclipse IDE
for C/C++ Developers, that's us, and
| | 03:16 | because I am coming to this web site on
a Windows machine, it's detected that I'm
| | 03:20 | running Windows, and this will say Windows.
I could select another one if I want to.
| | 03:24 | But right here it's got Windows 32
Bit and Windows 64 Bit, and I just
| | 03:29 | download the Windows 64 Bit version,
and you will see I already have that
| | 03:33 | here in my Downloads.
| | 03:34 | And so that's the version right there, it's
the same version that's on that web site today.
| | 03:38 | When you come to the web site, they are
likely be a different version, and you
| | 03:41 | can download that version.
| | 03:42 | So now we have all the pieces that we
need, I am going to go I am
| | 03:47 | going to close Firefox, and so we will
start by installing this latest version
| | 03:51 | of GCC from equation.com.
| | 03:52 | I am going to run the
installer as administrator.
| | 03:56 | So I right-clicked on that, and
I selected Run as administrator.
| | 04:00 | You see this lovely screen
here which has a license on it.
| | 04:03 | This is the GNU General
Public License. I just say Accept.
| | 04:08 | I have to put this in a particular
path where Eclipse will look for it.
| | 04:12 | This path will not work.
| | 04:13 | Any path that has a space in it will not
work, and in fact, Eclipse just expects
| | 04:18 | it to be in a very particular path,
and it's not the default path.
| | 04:21 | So, I am going to type here MinGW,
and the M is capitalized, and the G is
| | 04:27 | capitalized, and the W is capitalized.
| | 04:29 | So, I am going to go ahead and press Install,
and this will take a few minutes. All right!
| | 04:34 | We're going to say Finish, and we
usually get a little pop up window, there it
| | 04:39 | is that says it might not
have installed correctly.
| | 04:42 | This is the Windows Program Compatibility
Assistant, and you may safely ignore this.
| | 04:45 | I just press the red x.
| | 04:47 | So I am going to close this.
| | 04:49 | This is the Start Menu stuff,
and this is now properly installed.
| | 04:54 | So now we've installed our GCC Complier,
we are going to go we are
| | 04:57 | going to install Eclipse.
| | 04:59 | And to install Eclipse, it's
actually a little bit simpler.
| | 05:03 | Eclipse comes in the Zip file, and it's
just a bunch of files that you are going
| | 05:06 | to end up copying to Program Files.
| | 05:08 | So I am going to right-click on this,
and I am going to say Extract All, and I
| | 05:13 | am just going to take the default location here.
| | 05:15 | We'll end up being right
there in that same directory.
| | 05:17 | So I am going to click Extract,
and this takes a few minutes.
| | 05:22 | So now this is the directory that it's
been copied into, and what I do is I just
| | 05:28 | come down here in the sidebar.
| | 05:29 | The idea is you want to copy this into
the Program Files directory, and this
| | 05:33 | is the 64-bit version, so I want it in the
64-bit Program Files which does not say x86.
| | 05:39 | And I just drag this and move it right there.
| | 05:43 | There it is eclipse, and
there is all that stuff.
| | 05:46 | So I want to right-click
and pin it to the Start Menu.
| | 05:51 | So then it shows up right
there in the Start menu.
| | 05:54 | Looks like I may have previously pinned
it down there, but you can pin it there
| | 05:58 | as well if you like.
| | 05:59 | So now we close this, and at this point,
because this is Windows, it's probably
| | 06:03 | a really good idea to log out, and log
back in or even reboot your machine just
| | 06:07 | to make sure that all of
your paths are set up properly.
| | 06:10 | So now we've installed our compiler,
we've installed Eclipse, we have Java,
| | 06:15 | and so we can go we can
run Eclipse, and so I am going click on
| | 06:20 | Eclipse in my Start menu.
| | 06:21 | You notice I get this little
security warning the first time.
| | 06:24 | I am going to uncheck this
Always ask, and I am going to say Run.
| | 06:28 | So, it's asking me to select a
workspace, and I am just going to leave the
| | 06:32 | default, and I am going to
say OK, and there is Eclipse.
| | 06:35 | So, I am just going to press the
Maximize button here, and I'm going to go to
| | 06:40 | the Workbench which is this button over
here on the right, and there is Eclipse,
| | 06:44 | and it's already set up for our C++ perspective.
| | 06:48 | If yours is not set up for your C++
perspective, you can write this one here,
| | 06:52 | Open Perspective, and select Other,
and then find your C++ perspective, and
| | 06:58 | open that, and that will give you the C++
perspective which is the layout of the screen here.
| | 07:04 | So, before we do anything else,
we want to go into Preferences.
| | 07:07 | So, we are going to click on the Window
menu and select Preferences, and under
| | 07:11 | General, I am going to open the little
disclosure triangle here next to General.
| | 07:15 | I am going to click on Workspace, and
you notice down here at the bottom the
| | 07:18 | Text file encoding, this is very important.
| | 07:20 | Our files are cross-platform, and
they are in UTF-8, and that is not the
| | 07:26 | default for Windows.
| | 07:27 | They will probably work just fine, at
least most of the time, but UTF-8 is now
| | 07:33 | the standard, and so if you are working
with source files, especially if you are
| | 07:37 | working with source files that you are
going to share with anybody else that
| | 07:41 | might be working on a different
operating system, you are going to want to make
| | 07:45 | sure that you are using UTF-8.
| | 07:46 | So I am going to select Other here, and the
dropdown box, and I am going to select UTF-8.
| | 07:51 | And under New text file line delimiter,
I want to select Other, and I want to
| | 07:55 | select Unix because Windows line
delimiters are different and these files are
| | 07:59 | cross-platform, and Unix is the standard.
| | 08:02 | Now, next thing I want to do is I want
to come here under C and C++, and I am
| | 08:06 | going to open that disclosure triangle.
I am going to go to New CDT Project Wizard.
| | 08:13 | You see under Executable, I am going to
make sure that, that's opened up, and I
| | 08:17 | am going to select Empty Project.
| | 08:19 | And yours will probably say
Cross GCC, that's not correct.
| | 08:21 | You want to make sure this says MinGW
GCC, and then you want to click on this
| | 08:26 | Make toolchain preferred and so you will get
a little arrow there next to your MinGW GCC.
| | 08:32 | So, we will close the C/C++, and we are
going to come back up under General, and
| | 08:36 | we are going to go to Editors, and Text
Editors, and we're going to check every
| | 08:43 | box in this except for Insert spaces for
tabs and Show print margin, and so I am
| | 08:49 | going to select Show line numbers, Show
whitespace characters and make sure all
| | 08:52 | of these are checked, and leave the
Displayed tab width to 4 and leave
| | 08:56 | everything else like it is.
| | 08:58 | So now we are going to close the
General Tab, and we are going to open up the
| | 09:01 | C and C++ Tab again, and we are going to go
to editor, and we are going to select Folding.
| | 09:07 | Here, you want to select everything at
the top, and all these, in these little
| | 09:11 | box that says Initially fold
these regions, these all get unselected.
| | 09:14 | So, I am going to uncheck all of those,
and I am going to check all of these,
| | 09:19 | and that enables code folding, but
it doesn't initially fold anything.
| | 09:23 | So, that's all the preferences for now.
| | 09:25 | We will be setting some more
preferences in a few minutes.
| | 09:28 | So I am just going to select OK down
here, and I am going to come up here and
| | 09:32 | create a new project.
| | 09:34 | So here is the little new project, and
you see little arrow there, the dropdown
| | 09:38 | arrow, and I am just going to select
the one that says Project, and I am going
| | 09:41 | to select a General project.
| | 09:44 | So I will open up General, and I
select Project, and I say Next.
| | 09:48 | Our project name is going to be
CppEssentialTraining with no spaces in it, and
| | 09:55 | we'll go ahead and use the
default location, and select Finish.
| | 09:57 | Now, we are going to create a
new folder within this project.
| | 10:01 | So I am going to right-click on the
project, and I am going to say New > Folder,
| | 10:07 | and under Folder name,
there is an Advanced button.
| | 10:10 | I am going to select that button,
and then I am going to select Link to
| | 10:14 | alternate location, and press the Browse button.
| | 10:16 | So what this will do is it will allow
us to import our exercise files without
| | 10:20 | actually needing to make a
copy of the entire directory.
| | 10:23 | So, I am going to browse there, and
on the Desktop, you see exercise files.
| | 10:29 | I am just going to select the exercise
files, and I say OK, and make sure this
| | 10:34 | link is selected, and then I press Finish.
So now we have our exercise files.
| | 10:39 | You notice the little Link icon there,
and there they all are. All right!
| | 10:43 | So I am just going to close all that
up and create one more project here,
| | 10:47 | and this is actually going to be a C++
project, and so I am going to call it Working.
| | 10:53 | You will notice down here under
Toolchains, the MinGW should be selected.
| | 10:57 | If MinGW is not selected, then you
missed something in your configuration, in
| | 11:02 | your preferences, and you want
to go back and do that again.
| | 11:05 | So, this creates our Working
project, and I select Finish there.
| | 11:09 | This selects our Working project, and
this is where we are actually going to be
| | 11:12 | doing all of the compiling.
| | 11:14 | We are going to be copying files from
our exercise files, and putting them in
| | 11:18 | our Working project and using them there.
So let's go ahead and do that.
| | 11:22 | We are going to come into our exercise
files, we are going to go into Chapter
| | 11:25 | 2, and I am going to select version-test.
cpp, and I am going to press Ctrl+C on
| | 11:30 | my keyboard to copy that, and then I
am going to select the Working project
| | 11:33 | down here and press Ctrl+V to paste it,
and that will make a working copy of
| | 11:38 | the version-test.cpp.
| | 11:39 | See we have one down here,
and it still exists up there.
| | 11:43 | When I double-click on this, it
opens it up in the editor, and it should
| | 11:47 | look just like that.
| | 11:48 | So this is just a little C++ file
for testing the version of GCC that we
| | 11:53 | have installed here.
| | 11:54 | So, the first time through when we just
created this Working project, we are not
| | 11:58 | going to be able to just press the
green Build and Run because this Working
| | 12:02 | project hasn't been used yet.
| | 12:03 | So, the first thing we actually have to
do is we need to come in to the Project
| | 12:08 | Menu and select Build All.
| | 12:09 | Once that's done, then we can select
this Build and Run button, and you see it
| | 12:15 | compiled our source file, and
it gave us a result down here.
| | 12:19 | So, the result down here, it's
under the Console Tab, and it already
| | 12:22 | selected that tab for you.
| | 12:24 | At this point, you should be seeing a
version number that says 4.7.0 or later if
| | 12:29 | you have installed a later version of GCC.
| | 12:31 | Now, we're not quite done
but we are getting there.
| | 12:34 | At this point, we need to finish
setting up our Working project environment.
| | 12:38 | So you can right-click on Working
and my screen is so small here for the
| | 12:42 | purposes of teaching.
| | 12:44 | I have to scroll down, and you will find
Properties all the way down at the bottom.
| | 12:48 | So I am going to select Properties there,
and I am going to come down here into
| | 12:52 | C/C++ Build, and I am going to open
that up, and I am going to select Settings,
| | 12:57 | and you should see a
screen that looks like this.
| | 12:59 | Again, the screen here is a
little bit small, so this scrolls.
| | 13:02 | So this is not going to look
exactly like it looks on yours.
| | 13:06 | And when I select these things, it goes
and scrolls for me, so it look a little
| | 13:10 | bit weird, but the first thing we do is come in here
under C++ Compiler, and select Miscellaneous.
| | 13:16 | So if I just select C++ Complier,
you will see, it scrolled there for me.
| | 13:21 | It's got my Command:
g++ and all of my options.
| | 13:24 | And so we are going to be changing those
options but you can't change them here,
| | 13:28 | and so you need to select Miscellaneous,
and under Miscellaneous, under Other
| | 13:32 | flags, put the cursor in there, and
you're going to type exactly this, -std as
| | 13:38 | in standard, std=c++11.
| | 13:43 | Then you are going to come down here
under GCC C Complier, that was for the C++
| | 13:47 | Complier, under the C Complier all the
way down at Miscellaneous, and you are
| | 13:52 | going to do it again, same thing,
| | 13:54 | come into the Other flags, and go in
there, and you're going to type -std=, and
| | 13:58 | it's a little bit different, gnu11.
| | 14:02 | So that sets up the C++ Complier so
that it will compile with the latest
| | 14:06 | standard of C++ which is C++11, and it
sets up the C Complier so that it will
| | 14:12 | compile with the latest C standard which
is C11 with a few small GNU Extensions.
| | 14:17 | Now, we're almost done.
| | 14:19 | We are going to go into the Run/Debug
Settings which is right here, and select
| | 14:23 | our Working project, that says Working.
exe, and I am going to click on Edit.
| | 14:29 | And then, under the second tab here that says
Arguments, I am going to type in some Arguments.
| | 14:33 | I am going to type in one two three,
and I am typing those words out;
| | 14:38 | one two three, and they
have spaces between them.
| | 14:41 | These are like Command Line Arguments,
and we use these occasionally in the
| | 14:45 | course to test and work with the
Command Line Arguments that you might use on a
| | 14:49 | console-based application.
So that's all there is to it.
| | 14:53 | I am going to press OK there.
| | 14:55 | I am going to press OK down here,
and now we should be all set up.
| | 14:58 | I am going to select the Build and
Run button, and you see it complies
| | 15:03 | everything now with the correct standard.
| | 15:05 | Now, I can uncomment this code
here because this is C++ feature test.
| | 15:12 | These are some features that are only
available in C++11, they are not available
| | 15:15 | in older versions of C++.
| | 15:18 | So, the GNU Compiler wouldn't have
worked with these if I hadn't set those
| | 15:22 | flags to set up C++11.
| | 15:25 | So I am going to uncomment them, and I
can do that by just pressing the Ctrl and
| | 15:30 | the Slash key on my keyboard, and
that's a Eclipse shortcut for uncommenting
| | 15:35 | that, and then Ctrl+S to save, and you see my
little star went away up there. So now it's saved.
| | 15:40 | And I can press the Compile and Run
button again, and it compiles, and it runs
| | 15:45 | without error, and you can see we have
our output, and it says one two three,
| | 15:48 | and I have initialized this vector
with an initializer list which is a C++11
| | 15:53 | feature, and I am using the Range-
based for loop which is a C++11 feature.
| | 15:58 | So we can see that that's working with C++11.
Now, I am going to delete our Working file.
| | 16:05 | I select it, and I press the Delete
key on my keyboard, and I select OK here.
| | 16:10 | And I am going to come up here to my
Project, and I am going to say Clean, and I
| | 16:15 | am going to make sure that Clean all
projects is selected, and press OK, and
| | 16:19 | there it's cleaned the project.
| | 16:20 | Now, I am just going to copy and paste
the c99.c and select our Working project,
| | 16:26 | and press Ctrl+V to paste it.
| | 16:29 | I am going to open that up in the editor,
and this will check to make sure that
| | 16:33 | we have the latest version of the C
Complier selected in our command line
| | 16:37 | switches, and I am going to select
the Compile and Run button, and you see
| | 16:42 | that, that works fine.
| | 16:44 | It's also testing that we
have our Command Line Arguments.
| | 16:46 | Here is zero, one, two, three,
those are our Command Line Arguments so
| | 16:49 | that's installed right.
| | 16:51 | This syntax here, both declaring and
initializing the integer inside the for
| | 16:55 | loop, that's a c99 feature, so the
compiler does not work with that unless we
| | 16:59 | have that compiler switch set.
So, all of this is working exactly as it should.
| | 17:04 | So, I am just going to select this file,
and I am going to delete it, and I am
| | 17:09 | going to run Project and Clean, and
Clean all projects is set, and that's okay.
| | 17:14 | And that gets us all set up for
the first lesson in the course.
| | 17:17 | So, each time you use the Working
project, when you're all done, you need to
| | 17:22 | delete whatever working files you put in
there, and you need to run Project > Clean.
| | 17:27 | The short version and the reason for
this is that if you leave those files
| | 17:30 | there, it will create conflicts
when you try to use the project for the
| | 17:34 | next example files.
| | 17:36 | The way Eclipse is set up, it will
compile all the files in a project.
| | 17:39 | And as you will learn later in the
course, you can only have one instance of
| | 17:43 | the entry point for a project which
is called main, and since each of our
| | 17:47 | example files has its own main, you can
only have one of them in the folder at
| | 17:51 | a time, and you need to run Setup
Clean each time to reset the Working project
| | 17:55 | for the next source file.
| | 17:56 | So, now we have a working Eclipse with the latest
GCC installed and running on a PC, running Windows 7.
| | Collapse this transcript |
| Working with Eclipse on Windows| 00:00 | If you are running Eclipse on Windows
you need to be aware of one important and
| | 00:04 | quirky behavior, every time you change
the main file in a project, and we will
| | 00:08 | be doing that for just about
every movie in this course.
| | 00:10 | Eclipse could get confused and not
realized that its file system is out of sync.
| | 00:15 | Let's take a quick look at this behavior.
| | 00:17 | I am going to go ahead and make a
working copy of version-test.cpp, so I select
| | 00:21 | it here, and I press Ctrl+C, and then I
select Working, and I press Ctrl+V. And
| | 00:27 | that copies and pastes it
into the Working project.
| | 00:30 | Now I am going to double-click on it,
and that opens it up, I am just going to
| | 00:34 | press this Run button up here, and that
compiles it, and it runs it, and it runs just fine.
| | 00:40 | Now I am going to close this, and I am
going to delete it from the Working file system.
| | 00:45 | I am going to come up here and grab a
different one, let's grab hello.cpp.
| | 00:52 | I will press Ctrl+C to Copy it and select
Working and Ctrl+V to Paste it and open it up.
| | 00:59 | Now I am just going to press this Run button
again which ought to compile it and run it, right?
| | 01:04 | You notice we have an error, say No,
and I will hover over this, it says first
| | 01:09 | defined here, that's not very helpful.
Look down here and ah!
| | 01:13 | Multiple definition of main.
| | 01:16 | So what that means is that there's
another object file in our project that
| | 01:21 | already has main defined.
| | 01:23 | If I look over here in Debug, I am
going to open this Disclosure triangle here,
| | 01:27 | you see we have two object files;
| | 01:29 | hello.0 and version-test.o. Well,
that's not right, and that won't work.
| | 01:33 | So the solution here is to
run something called Clean.
| | 01:37 | We'll come up here to the Project menu,
and I am going to select Clean, I am
| | 01:41 | going to select Clean all projects and say OK.
| | 01:44 | And you notice that that deletes the
whole Debug directory, it also deletes
| | 01:48 | the Binaries directory.
| | 01:49 | And now when I press the Run button, it
compiles, and it runs and everything is
| | 01:56 | fine, and we look in the Debug folder,
we see we have Working.exe, and we have
| | 02:00 | hello.o, and that's exactly
what we are supposed to have.
| | 02:03 | So the problem here is that every
time we delete a C file or a CPP file and
| | 02:08 | copy and paste a different one into the
Working folder we have this potential conflict.
| | 02:13 | The easiest solution is to do a Clean
whenever you delete a file in the Working Project.
| | 02:19 | This seems to ensure that
you won't see this problem.
| | 02:21 | So I am going to go ahead and do that right now.
I am going to take this hello.cpp.
| | 02:26 | I am going to delete it, I am pressing
the Delete key on my keyboard and OK.
| | 02:30 | And now it's deleted, and now I am just
going to come right up here to Project
| | 02:33 | and select Clean, unfortunately
there's no button for this on the Toolbar.
| | 02:37 | Clean all projects is selected, I am
going to press OK, and now it's clean, and
| | 02:41 | now we are ready to begin the next movie.
| | 02:43 | This problem doesn't seem to happen
in Eclipse on other OSs, it's no use
| | 02:47 | speculating how or why this is a
problem on Windows, it's just something that
| | 02:51 | you need to be aware of, so you know what's going on
and what to do about it when you see this behavior.
| | Collapse this transcript |
| Setting up Eclipse in Ubuntu Linux| 00:00 | In this movie, we're going to install
the Eclipse C Development Tools on a PC
| | 00:05 | running Ubuntu 12.04 Precise Pangolin.
| | 00:09 | Note that it's not necessary to
install Eclipse in order to take this course.
| | 00:14 | You may use whatever
development environment you like.
| | 00:16 | In fact, I encourage you to use
your own development environment.
| | 00:20 | I'm using Eclipse for the examples in this
course because it's convenient for this purpose.
| | 00:25 | It allows me to demonstrate the examples
in a way that is accessible to students
| | 00:29 | on any of the three major platforms today;
| | 00:31 | Windows, Mac, and Linux.
| | 00:34 | That is the only reason I'm
using Eclipse for this course.
| | 00:37 | I normally do my development work
with whatever tools are supported on the
| | 00:40 | platform I'm working on, and I
encourage you to do the same.
| | 00:44 | So the first thing we're going to do
is we're going to start up the Ubuntu
| | 00:47 | Software Center which is this little icon here.
| | 00:49 | We're going to use this to
check our version of GCC.
| | 00:53 | GCC is the new Compiler Collection.
| | 00:56 | That's the C Compiler that
we're using for this course.
| | 01:00 | So I simply type in gcc, and I see
that it's installed, and I click on
| | 01:04 | More Info, and I'm going to scroll down to
the bottom here where I can see the version.
| | 01:09 | I see that the version is 4.6.3. For
this course, you need at least GCC 4.7.0,
| | 01:16 | and the reason for that is that we're
teaching the C++11 standard and the C11
| | 01:21 | standard which were both just ratified
last year and are not fully supported in
| | 01:26 | GCC 4.6.3. Some of the later GCC 4.6s
had some of the features, but GCC 4.7 is
| | 01:34 | the minimum that we're using for this course.
| | 01:37 | So, for that reason, I'm going to
need to update the GCC on this computer.
| | 01:42 | So I'm going to type in up here gcc-4.7.
Searching in the Ubuntu Software Center
| | 01:48 | is a little bit weird, at
least as of this version.
| | 01:51 | So, there's no simple way for it to tell
me what's the latest version available,
| | 01:55 | I've actually installed some more
archives here, you probably have too;
| | 02:00 | you may need to have another archive
besides a default Ubuntu archive in order
| | 02:04 | to find the latest GCC.
| | 02:06 | So, this is the GCC 4.7.
I'm going to go ahead and install this.
| | 02:10 | It will install it on this computer in
addition to the GCC 4.6 that's already there.
| | 02:14 | We're going to have to update some
symbolic links in order to get it to work.
| | 02:17 | We'll get there in a minute.
| | 02:20 | And now that GCC 4.7 is installed,
we're going to do the same thing for G++.
| | 02:24 | G++ is the C++ Compiler that's part of
the GNU C Compiler Collection, but it
| | 02:30 | doesn't come installed by default.
| | 02:32 | So, here we can see that it's
not installed on this computer.
| | 02:35 | If I look inside the one that it found
here, well notice, at least in this case
| | 02:40 | because I noticed this before, it's 4.7,
but it's not the same 4.7 as the GCC
| | 02:46 | that I installed before.
| | 02:49 | If I come back here, and I type g++-4.7,
you'll see that I get a different version.
| | 02:55 | I will click on More Info down here.
| | 02:58 | See that this one says -3.
So, this is the one that I want to install.
| | 03:03 | So again, when you're installing stuff
like this on a Linux distribution, and
| | 03:07 | this is true with any Linux
distribution because of the open source nature of
| | 03:10 | it, you need to be careful about the
versions and make sure that they match.
| | 03:14 | So I'm going to click on Install here,
and this will install the GNU C++ Compiler. Okay.
| | 03:20 | Now that, that's done, I need to
go and update my symbolic links.
| | 03:23 | So I'm going to bring up the Terminal,
and I'm just assuming that if you're
| | 03:27 | using a distribution of Linux that
you're somewhat familiar with the Terminal,
| | 03:32 | so I may not explain all of the
steps as I go along. I'll do my best.
| | 03:36 | So first thing I'm going to do is
I'm going to type sudo which gives me
| | 03:39 | superuser root privileges, and I'm
going to type su - which will actually give
| | 03:45 | me a shell as root, and it
should ask for my password here.
| | 03:49 | And now, I am the most
powerful person on this computer.
| | 03:52 | It's possible to do a lot of damage.
| | 03:55 | You need to be very careful how you
type and what you type because there
| | 03:58 | are some commands that you could
type by mistake that could potentially
| | 04:02 | wipe out your system.
| | 04:03 | I don't mean to scare you, but you need
to be careful when you're typing as root.
| | 04:08 | So I'm going to change directories to user bin;
| | 04:10 | type cd /usr/bin, and I'm going to
look and see what we have here in terms of
| | 04:19 | these pieces of the GCC system.
| | 04:21 | So, I'm going to type ls -l, and I'm
going to type gcc* and g++* and these all
| | 04:30 | have spaces between them, and cpp*.
| | 04:34 | These are the three commands that
we need to see how they're linked up.
| | 04:38 | ls -l will give me a listing of the
directory with a lot of access information
| | 04:44 | that I actually need in this case.
| | 04:46 | We can see we have symbolic links for
cpp and gcc and those are the ones that
| | 04:52 | are highlighted in the light blue there.
| | 04:54 | You see that we also have g++-4.7,
and there's no symbolic link for G++.
| | 04:59 | So, I'm going to start by creating the
symbolic link for G++, and I'm going to
| | 05:06 | type ln -s for symbolic, g
++-4.7, and a space, and g++.
| | 05:13 | And what this command does is it will
create a symbolic link using g++-4.7 as
| | 05:19 | the source and g++ as the target.
| | 05:22 | And then when I say ln -s g++, I
meant to say ls -l g++, there we see that
| | 05:33 | it has the link now.
| | 05:35 | There is a g++ that is
linked to the file that we want.
| | 05:38 | Now, I need to do the same thing for
the ones that are already linked, which
| | 05:41 | means that I need to delete them first.
| | 05:43 | I'm going to type rm which is
the UNIX command for delete--
| | 05:47 | it's short for remove--and both cpp
and gcc, and that will remove those two
| | 05:53 | files that you see highlighted there,
they're the symbolic links to the old 4.6
| | 05:57 | versions, and now I'm going to create new links,
| | 06:00 | ln -s gcc-4.7, to gcc, and ln -s cpp,
which is the C preprocessor -4.7 to cpp.
| | 06:15 | Now, when I type that original command
again, ls -l gcc* g++* cpp*, you see that
| | 06:25 | we have exactly what we need.
| | 06:27 | Those symbolic links are now updated,
plus we have one for g++ and they're all
| | 06:31 | pointing to the 4.7 versions.
| | 06:34 | So now that, that's done, and it's
correct, I'm going to press Ctrl+D for David,
| | 06:38 | and that will get me out of my root shell,
and I'll press Ctrl+D again, and that
| | 06:43 | will close the Terminal.
Now, we're going to install the JRE.
| | 06:47 | JRE stands for Java Runtime
Environment, and this is necessary for Eclipse.
| | 06:52 | So I'm going to type in here default-jre.
| | 06:56 | Again, searching for things in Ubuntu
Software Center is a little bit of an
| | 07:00 | adventure, and so I'm just typing the
exact names because I know what they are,
| | 07:04 | and that may or may not actually
work for you if you're using a different
| | 07:08 | version of Ubuntu than I am. So, there it is.
| | 07:10 | The standard Java or Java-compatible
runtime, and I'm going to click on the
| | 07:14 | Install button, and that will install
Java, type in my password, and now the
| | 07:21 | Java Runtime is being installed.
| | 07:22 | So now that the JRE is installed, we can
finally install Eclipse, and we do that
| | 07:28 | by searching for Eclipse, eclipse-cdt.
| | 07:36 | CDT stands for the C Development Tools,
and that will install both the Eclipse
| | 07:42 | environment and the Development Tools.
| | 07:45 | So we'll click on that,
and we'll click on Install.
| | 07:50 | So now we have Eclipse installed which
requires the Java Runtime Environment, so
| | 07:54 | we have that installed, and we have
the correct version of the GNU Compiler
| | 07:59 | Collection, GCC installed, and so
now we're ready to start up Eclipse.
| | 08:04 | So, I'm going to close out the Ubuntu
Software Center, and I'm going to click on
| | 08:09 | this Dashboard and type in Eclipse just
the first couple of letters, you'll find
| | 08:14 | it there, and I'm going to
click on that to start up Eclipse.
| | 08:18 | And just as Eclipse starts running,
you'll see an icon come up here in the
| | 08:22 | Toolbar on the left.
| | 08:23 | So I'm going to right-click on Eclipse
here in the Toolbar, and I'm going to say
| | 08:27 | Lock to Launcher, and that way, it
will always be there in the Launch Bar.
| | 08:32 | Select a workspace, accept the default,
and press OK and also check this box
| | 08:37 | that says Use this as the default and do not
ask again, and it loads up all of its stuff.
| | 08:43 | I've had this experience before the
first time starting up Eclipse on Ubuntu,
| | 08:48 | and it doesn't actually
show me that it's got C++.
| | 08:51 | If I come in here to the Preferences,
I see that I have the C++ there.
| | 08:56 | So, if it didn't show up in here, my
experience is by closing Eclipse and
| | 09:00 | starting it up again, it
finds it. But there it is.
| | 09:04 | So the first thing I'm going to do is I'm
going to select the Workbench over here.
| | 09:08 | And if you know anything about Eclipse,
you'll see we have a perspective started
| | 09:12 | up that says Resource.
What we want is the C and C++ perspective.
| | 09:16 | So I'm going to go into Window, I'm
going to say Open Perspective, and there I
| | 09:20 | see the C/C++ in the menu.
| | 09:23 | Again, sometimes it doesn't show up,
in which case you can select Other and
| | 09:27 | select C/C++ that way.
| | 09:29 | And now, it's changed the
perspective when we have the C/C++ perspective.
| | 09:33 | Now, I'm going to come in here to
the Preferences under Window, and under
| | 09:38 | General, I'm going to open that
up and come down to Workspace.
| | 09:43 | And down here under Text file encoding,
you see it says Default (UTF-8), and
| | 09:47 | that's exactly what we want.
| | 09:48 | If it does not say UTF-8 on yours,
you can select Other, and select UTF-8
| | 09:53 | from this dropdown.
| | 09:54 | But we're going to leave the default
there because that's correct on this one.
| | 09:58 | Also, under General, I'm going to open up
Editors, and I'm going to select Text Editors.
| | 10:03 | We're going to check a few boxes in here.
| | 10:05 | I'm going to leave Insert spaces for
tabs unchecked, I'm going to leave Show
| | 10:09 | print margin unchecked, I'm going to
check the Highlight current line, actually
| | 10:13 | everything else in here except those two;
| | 10:16 | Spaces for tabs and Print margin,
everything else in here gets checked.
| | 10:20 | Now, we're going to close General,
and open up C and C++, and I'm going to
| | 10:26 | select on the New CDT Project Wizard.
| | 10:28 | And under Preferred Toolchains, Empty
Project, I'm going to select Linux GCC and
| | 10:35 | press this button that
says Make toolchain preferred.
| | 10:38 | You'll notice that it puts a little arrow
next to that one, and that's what you want.
| | 10:44 | And then here under editor, I'm going to
open the disclosure triangle and press Folding.
| | 10:49 | You want all of these check boxes
checked that enable the various types of
| | 10:53 | folding, and you want all of these
unchecked in the initially fold region.
| | 10:59 | So that's the preferences for now.
| | 11:01 | We're going to set some other preferences
in our project after we create a project.
| | 11:05 | So now we're going to
create a couple of projects.
| | 11:07 | We're going to actually create two projects.
| | 11:09 | One of them is going to hold all of
the exercise files, and the other one is
| | 11:13 | actually going to be for compiling.
| | 11:15 | And the reason for that is you can
really only compile one of these files at a
| | 11:19 | time, and Eclipse likes to
compile all the files in a project.
| | 11:22 | So I'm going to select this little
arrow next to the New button, and I'm
| | 11:26 | going to say Project...
| | 11:28 | just the normal project,
not any of these other ones;
| | 11:31 | just Project with the dots, and under
General just the one that says Project,
| | 11:37 | press the Next button,
and give the project a name.
| | 11:39 | This is going to be CppEssentialTraining,
and you notice I don't put any spaces in that.
| | 11:45 | My programming projects, I really
like to have folder names that don't
| | 11:49 | have spaces in them.
| | 11:50 | That's getting harder and harder to
do as desktops get more sophisticated.
| | 11:53 | But there's still a lot of tools out
there that will complain about spaces in
| | 11:57 | file names and folder names.
| | 11:58 | So I'll press Finish, and that gives us
this empty project, and it's got nothing
| | 12:03 | in it, and so we're
going to put something in it.
| | 12:05 | I'm going to right-click on this and
under New > Folder, come down here and
| | 12:09 | select the Advanced button, and this
allows to link to an alternate location.
| | 12:13 | This way, we can load up the exercise
files, and not have it make a copy of
| | 12:18 | them into our workspace.
We don't really need that.
| | 12:20 | We're not going to actually be
editing these files in place anyway.
| | 12:23 | So I'm linking to this alternate location,
and select Browse, and under Desktop,
| | 12:29 | you see ExerciseFiles, and select OK.
| | 12:33 | So I've got my exercise files on the
Desktop, you might have yours some place else.
| | 12:38 | When you're browsing, you can find yours.
| | 12:40 | Now I'll select Finish, and there is
our exercise files inside that project.
| | 12:44 | So, when I click on the disclosure
triangle, you see we've got all of our
| | 12:48 | folders, and there's all of our exercise files.
So I'm going to leave that alone for now.
| | 12:53 | I'm going to create a new project
and so I just right-click on this area
| | 12:57 | where you can select the arrow next to the
New Project up here, and select C++ Project.
| | 13:02 | And this one is going to be called
Working, and this is where we're actually
| | 13:05 | going to do our work.
| | 13:07 | You'll notice that the default empty project,
it's got the Linux GCC Toolchain. That's important.
| | 13:12 | If you don't see that arrow there,
then you need to go back and do your
| | 13:16 | preferences configuration
again because you missed something.
| | 13:19 | Select Finish, and there's our Working
project, and so I'm going to open that one up.
| | 13:25 | You see it's just got the Includes in it.
| | 13:26 | Now, it will have more things in
it once we do a build inside there.
| | 13:30 | So I'm going to open the disclosure
triangle on our C++ Essential Training
| | 13:34 | and on our ExerciseFiles and on Chap02,
and I'm going to come down here and
| | 13:38 | select version-test.cpp.
| | 13:40 | Now, I'm pressing Ctrl+C on my keyboard
to copy that file, and I'll just close
| | 13:46 | all of that and select Working and
press Ctrl+V to paste it, and now I have a
| | 13:51 | copy of that file inside the Working folder.
Double-click on it, and that will bring it up.
| | 13:58 | Now, there's another little quirk
you may run into with Eclipse here.
| | 14:01 | The first time it runs and the first
time it runs a project, sometimes it will
| | 14:05 | show some errors in the file.
| | 14:06 | You can ignore those and just
let it sit there for a few minutes.
| | 14:10 | They'll actually go away as it finds
all of its header files, and it builds all
| | 14:13 | of its indexes inside.
| | 14:15 | So now, I'm going to go
I'm going to press Build, and it's this
| | 14:19 | little Hammer icon up here,
and that will build the project.
| | 14:23 | And then I'm going to select Run up here,
the larger of the two green buttons,
| | 14:27 | and that will run, compiles it if it
needs to, and it runs this, and you see
| | 14:31 | that we have our results down there.
| | 14:33 | It says GCC version:
4.7.0 and Version string:
| | 14:37 | 4.7.0. So this tells us that we have
the right version of GCC that it's
| | 14:42 | installed that it's working.
| | 14:44 | Our Toolchain is doing
everything that it needs to do.
| | 14:47 | There's one more bit of configuration
that we need to do because the way that
| | 14:51 | this is installed by default,
it's not supporting C++11.
| | 14:56 | So if I select this part that's
commented out and press Ctrl and the Slash
| | 15:00 | key on my keyboard, it will uncomment that,
and that's a little Eclipse shortcut there.
| | 15:04 | Well, I press Ctrl+S to save, and then
I press this Run Working button again.
| | 15:10 | And you notice that it has errors, and
I'll say No, we're not going to run it anyway.
| | 15:16 | These lines here are complaining about
features that aren't in C++98 which is
| | 15:20 | the default mode of the GCC 4.7 Compiler series.
| | 15:25 | So if you're not seeing those errors,
that means that you've got a later version
| | 15:28 | of GCC that's defaulting to C
++11, and that's wonderful.
| | 15:32 | We're going to go ahead and do a
little more configuring inside the project.
| | 15:35 | I want you to follow along, and you
won't need to set the standard strings, but
| | 15:39 | you'll need to follow along to do a
little bit of other configuring anyway.
| | 15:43 | So I'm going to right-click on the
Working project, and I'm going to scroll all
| | 15:47 | the way down to the bottom here under
Properties, and I'm going to open up the
| | 15:51 | C++ Build disclosure triangle,
and I'm going to click on Settings.
| | 15:55 | Here's where we set the
versions of the Compiler.
| | 15:57 | For the C++ Compiler, click on
Miscellaneous there, and then, here under Other
| | 16:02 | flags, I'm going to put in here -std,
which means standard, =c++11.
| | 16:11 | And again, if your Compiler is already
doing that, then you might not need this
| | 16:15 | string or it might already be there.
| | 16:17 | Then under the C Compiler,
I'm going to do the same thing.
| | 16:21 | I'm going to come down here under
Miscellaneous, I'm going to say -std=gnu11,
| | 16:26 | and that's the C11 standard with a
couple of GNU extensions. All right!
| | 16:31 | So once those are done, I'm going to
scroll down here, and I'm going to click
| | 16:35 | on this Apply button.
| | 16:36 | And then there's one more bit of
configuring we want to do here under
| | 16:39 | Run/Debug Settings.
I'm going to select Working;
| | 16:42 | that's our Working project, and I'm
going to press Edit, and then I'm going to
| | 16:46 | select Arguments here.
| | 16:47 | Occasionally, we're going to want
to run a program as if it has some
| | 16:51 | Command Line argument.
So I'm just going to type those in here;
| | 16:54 | one two three and press OK and
press OK, and now we're all ready.
| | 17:01 | Now, when I run this again, you'll
notice, it will recompile it, and
| | 17:06 | everything will work.
| | 17:07 | So, click Run, and now it's working.
It's showing the one two three.
| | 17:12 | That's actually this vector string 1.3
because I'm testing the C++11 feature.
| | 17:18 | Here's the whole file, by the way.
| | 17:21 | This C++11 feature that has initializer
lists, and also the range-based for loop.
| | 17:26 | These don't work in earlier versions of
C++, they're incredibly useful, and we
| | 17:31 | are going to be using them in this course.
| | 17:33 | So now I'm going to go I'm
going to delete version-test.cpp from
| | 17:38 | the Working project.
| | 17:41 | The short version of the reason for this
is if you leave it here, it will create
| | 17:44 | conflicts when you try to use
this project with the example files.
| | 17:47 | A little more explanation, the way
Eclipse is set up, it will compile all
| | 17:51 | the files in a project.
| | 17:52 | And as you'll learn later in the course,
you can really only have one instance
| | 17:56 | of a main function, the entry point to
any C++ project in a given compile set.
| | 18:03 | So since each of our example files has
its own main, you can only have one of
| | 18:06 | them in this folder at a time.
| | 18:08 | So at the end of every one of these
lessons, we're going to be deleting whatever
| | 18:12 | is in Working so that we have
a fresh working to start with.
| | 18:16 | So, I'm going to press the Delete key
on my keyboard, and I'm going to say OK,
| | 18:20 | and that deletes it from there,
but of course, it still exists in the
| | 18:24 | ExerciseFiles because we were working on a copy.
| | 18:27 | So now you have a working Eclipse with the latest
GCC installed, and running on a PC running Ubuntu.
| | Collapse this transcript |
| Understanding the development cycle with "Hello, World"| 00:00 | Before we can really dive into the
examples we need to learn how to work our tools.
| | 00:04 | For most of you, the Eclipse environment
will be new, and it will not ultimately
| | 00:08 | be the tool you'll use to develop in C and C++.
| | 00:11 | Even for those of you who are familiar
with Eclipse, and even those of you who
| | 00:15 | are going to be using it to develop
in C and C++, our development cycle for
| | 00:19 | these exercises will
probably be different anyway.
| | 00:22 | So let's take a few minutes now,
learn how this works for the purpose of
| | 00:26 | following along with the exercises in
this course, and the time spent now will
| | 00:30 | serve you well later on.
| | 00:31 | So let's start by making
a working copy of a file.
| | 00:34 | We're going to select hello.c.
That's the traditional way to do this.
| | 00:38 | We use a Hello World example.
| | 00:39 | It's very simple, we know there's not
much that can go wrong with it, and we can
| | 00:43 | really focus on the development
environment, and I'm going to copy and paste.
| | 00:48 | You can right-click or Ctrl-click on
a Mac, and you can select the copy and
| | 00:52 | paste here from the Context menu or
what I am going to do is I am going to get
| | 00:56 | used to using my keyboard.
| | 00:58 | I am on a Mac here, so I am going to
press Command+C, you'd press Ctrl+C if
| | 01:03 | you're on a PC, and that will copy this,
and it puts in the copy buffer, and
| | 01:07 | then you select the Working folder down here;
| | 01:09 | it's a seperate project actually, the
Working project, and you press Ctrl+V on a
| | 01:14 | PC, or I am going to press
Command+V on this Mac to paste it.
| | 01:18 | It's good to get into the
habit of doing it that way.
| | 01:21 | If you want to drag it and hold
a special key, you can do that.
| | 01:24 | You just need to be careful that you're
not making a link back to the original
| | 01:28 | file or moving the original file.
It's just a whole easier to copy and paste.
| | 01:32 | So I am going to double-click on hello.c, and there it is
very simple comment at the top, #include <stdio.h>.
| | 01:38 | We'll learn all about these
different parts of the C program later on.
| | 01:42 | What we have here is just a really
simple example of a very minimal C program
| | 01:46 | that we can use for this purpose.
So at this point, there is different options,
| | 01:50 | we can do build, we can do run.
| | 01:52 | For most purposes, pressing the Run
key here would work fine, and yet on some
| | 01:57 | platforms, and if you're running on a PC,
make sure you take a look at the movie
| | 02:01 | Working With Eclipse on Windows to
understand the problems that sometimes
| | 02:05 | happens on Windows computers.
That may not actually work.
| | 02:08 | You might need to do a clean first.
So we're going to start with doing a clean.
| | 02:12 | We're going to come up here to the Project menu.
| | 02:15 | Unfortunately, there's no shortcut key,
there's no icon on the Toolbar for this,
| | 02:18 | you just have to go up to the
Project menu, and select Clean.
| | 02:21 | What this does is it cleans all the
files that may have been lingering from
| | 02:25 | anything that we ran before.
| | 02:27 | So I am going to select Clean all
projects, and press OK, and that makes sure
| | 02:31 | that our project down here is in a
clean state and ready to compile.
| | 02:35 | Once that's happened if I press this Run
button, it's the big green one, it will
| | 02:40 | actually compile and run
this project without a problem.
| | 02:44 | The other option is to press Build first,
and Build will always build the entire
| | 02:49 | project and then Run will run it.
And there we have it running again.
| | 02:56 | It's just good to play around with this,
try some different combinations of it,
| | 02:59 | erase the hello.c, copy it back, maybe
try some of the other files from that
| | 03:03 | chapter 2 folder and run them, and get
a good idea for the environment here and
| | 03:07 | what can go wrong and what works.
| | 03:09 | Taking the time to do that at
this point is always a good idea.
| | 03:13 | Let's take a moment here and also
try the CPP version, the hello.cpp.
| | 03:18 | So I am going to delete hello.c,
because remember you cannot have two different
| | 03:22 | source files with main in
them in the same project.
| | 03:25 | So I am just going to press Delete here,
select hello.c, and Delete, and press
| | 03:29 | OK, and that deletes it.
| | 03:31 | I am also going to come
back up here and press Clean.
| | 03:34 | Try and get into the habit of doing
this every time you delete a file, Clean
| | 03:40 | all projects, and then we're going to
come back and select hello.cpp, this is
| | 03:44 | the C++ version of it, and Command+C
copy or Ctrl+C on a PC, and Command+V
| | 03:51 | paste or a Ctrl+V on a PC.
I am going to I double-click on it.
| | 03:55 | That brings it up here.
You can see it's slightly different.
| | 03:58 | It's pretty much the same program, but with
some C++ idioms in it, and it's in the C++ file.
| | 04:03 | I am just going to press that Run,
because we already did a clean when we
| | 04:07 | deleted the other file.
| | 04:08 | So Run should work fine, and
that compiles it, and it runs it.
| | 04:12 | So you will notice in the Debug folder
here, we've got a couple of files in there.
| | 04:17 | There is the hello.o. That's the object file.
| | 04:20 | And in Binaries, we have
Working, that's the executable file.
| | 04:26 | And look around in those directories
and see what you find, get familiar
| | 04:29 | with this environment.
| | 04:32 | It's also useful to understand what happens
when we introduce some errors into our code.
| | 04:36 | If I misspell cout just
put an X there, and save it.
| | 04:40 | I am pressing Command+S on my keyboard,
Ctrl+S if you're on a PC, and try and
| | 04:45 | compile, and run it.
| | 04:46 | You see that we get errors,
and we have an error up here.
| | 04:49 | If I hover over it, it says xcout was
not declared in this scope, symbol xcout
| | 04:54 | could not be resolved.
| | 04:55 | Get an idea of what some of
these error messages look like.
| | 04:59 | Go ahead and delete that and save it
and run again, and now it works fine.
| | 05:04 | Let's get rid of the semicolon and see
what happens when we get rid of the semicolon.
| | 05:09 | And I'll Save and sometimes when
you press that Run, it goes and does
| | 05:14 | whole build instead.
| | 05:17 | This is just something
that Eclipse does. Press OK.
| | 05:20 | I can always say Run in
the Background if I want to.
| | 05:23 | So it's good to understand that,
that's something you'll see now and then.
| | 05:26 | If I hover over this area, you see it
says expected ; before return, and
| | 05:32 | if I hover over this question
mark, it says missing ; .
| | 05:35 | You will notice that the Compiler
message, if we look down here at the compiler
| | 05:39 | message, it doesn't have the missing ; message.
That's actually from Eclipse's syntax checker.
| | 05:45 | So that's done by Eclipse
and not by the compiler.
| | 05:48 | That's why it's this yellow question
mark icon instead of one of the red icons
| | 05:52 | that you get from the Compiler errors.
| | 05:54 | So I will go ahead and I'll put that
semicolon back, and I will save, and I will build.
| | 05:59 | I am going to say Run in Background,
and there, it builds the file and runs it.
| | 06:05 | So play around a little bit, make some mistakes.
This is the time to get to know the tools.
| | 06:10 | Let's just go ahead and delete hello.cpp,
and I am going to run Clean.
| | 06:20 | You'll want to do this at the end of
every one of these movies so that you're
| | 06:24 | always in this clean state at the
beginning as you start the next lesson.
| | 06:29 | This should give you a good idea of how
you'll be using the Eclipse environment
| | 06:32 | to run the examples in this course,
because every environment is different and
| | 06:36 | really every project is different.
| | 06:38 | You'll want to go carefully through
this process at the beginning of every
| | 06:41 | project that you do so that you can
focus on the problem at hand later on rather
| | 06:46 | than worrying about your
development environment.
| | Collapse this transcript |
| Using stdout and stderr| 00:00 | For the purposes of this course, we will
be working with console-based applications.
| | 00:05 | These are small programs that communicate
with the user by sending plain text to a console.
| | 00:11 | C and C++ uses standard library that include
support for three standard streams of text.
| | 00:17 | In this movie, we will be discussing the
standard out and standard error streams.
| | 00:21 | Standard in will be discussed in next movie.
| | 00:24 | Let's start by making a working copy of
working.c. So I am going to copy that and
| | 00:31 | paste it down into our Working project
and double-click on it to open it up.
| | 00:38 | So you can see this is very simple,
it's just like the Hello, World!
| | 00:42 | And when I compile it and run it, and
you notice I ran Clean at the end of the
| | 00:47 | last time I used this.
| | 00:49 | So I am just going to click on the Run
Working button there, and when I compile
| | 00:53 | and run it, it displays
Hello, World! on the console.
| | 00:56 | This window down here is the console.
| | 00:58 | You see I have the tab selected,
this is console, and that's where the
| | 01:02 | messages are displayed that are sent
to the console from the standard output
| | 01:06 | stream in the C library.
| | 01:09 | So the function, printf is a very
common way to sent things to the console.
| | 01:13 | Printf is actually very powerful,
it has a lot of different capabilities.
| | 01:17 | But this is the simplest form, and
this is what it's very commonly used for.
| | 01:21 | There is another function called fprintf
with a f like Frank at the beginning of
| | 01:26 | it that is also commonly used.
| | 01:30 | And instead of just sending things to
the output stream, it will send things to
| | 01:33 | whatever streams you tell it.
| | 01:35 | So I can specify the standard output
stream by typing an stdout and a comma,
| | 01:41 | and that gives the standard output stream as
the first argument to the function fprintf.
| | 01:47 | So if I save this, I will press
Command+S on this Mac, Ctrl+S on a PC
| | 01:52 | and compile and run.
You see the effect is exactly the same.
| | 01:57 | Now I want to make a copy of this line
and paste it on the next line, and I am
| | 02:02 | going to change standard out to
standard error, err and save that and run it.
| | 02:09 | Now you will notice we have two lines.
| | 02:12 | The first line is in red, and that's
because it's the standard error stream and
| | 02:18 | the second line is in black
which is standard output stream.
| | 02:21 | And so this is an eclipse thing.
| | 02:23 | Things are sent to the standard error stream
come out in red on the console and eclipse.
| | 02:29 | In other environments, they work in
different ways and things would go to the
| | 02:33 | standard out stream or displayed
in black on the eclipse console.
| | 02:37 | You will notice that they are not in order.
They maybe in order on yours,
| | 02:41 | they may be out of order, this is a
little bit whimsical which one it ends up.
| | 02:46 | The reason for this is is that the
standard output is typically buffered in a UNIX
| | 02:52 | environment or an environment that
emulates UNIX which is most C compiler or
| | 02:56 | standard libraries and the standard
error stream is typically not buffered.
| | 03:02 | So the buffer isn't getting flushed
until the end of the program, here in this
| | 03:07 | case the end of main.
| | 03:08 | So the standard error is getting
displayed before the standard output even
| | 03:12 | though they're not in that order in the program.
This is typical behavior.
| | 03:17 | It's not surprising if
they're in any order whatsoever.
| | 03:20 | Now let's take a look at how this works in C++.
| | 03:22 | I am going to go ahead and delete
working.c, and I am going to run clean, and
| | 03:31 | I am going to take a copy of working.cpp
and select working and paste,
| | 03:37 | double-click to bring it up, and we will
go ahead and press the green Run button.
| | 03:43 | So this is pretty much the same effect,
but it's using some C++ paradigms.
| | 03:47 | You will notice that I have iostream
in the include there, and I am using
| | 03:52 | cout to display text.
| | 03:55 | So cout sends things to
the standard output stream.
| | 03:59 | If I copy and paste this and change cout
to cerr, we will save and run, you will
| | 04:09 | see I get that same result again.
| | 04:10 | I have got the red which means the
standard error and the black which is the
| | 04:15 | standard output and again, they are out
of order on mine and they may or may not
| | 04:19 | be out of order on yours.
| | 04:20 | Another interesting paradigm in C++ is
instead of these new line characters, \n
| | 04:26 | is a meta-sequence for a new line.
| | 04:29 | Instead of that, I can stream endl,
and I can actually do that on both the
| | 04:36 | cout and the cerr.
| | 04:40 | When I save and run, you will see
that those new lines are still getting
| | 04:44 | inserted, they are still on separate lines.
| | 04:46 | This is another common
paradigm that you'll see in C++.
| | 04:51 | You will see this endl instead
of the new line in the stream.
| | 04:55 | Another advantage of endl is it
actually flushes the output stream buffer.
| | 04:59 | It does both things;
| | 05:00 | it sends a new line, and it flushes the
buffer and so you will see that often.
| | 05:05 | Also you will notice that if I comment
out this line using name space standard,
| | 05:10 | and I am just going to comment that out,
all of a sudden, these tokens for cout
| | 05:15 | and cerr and endl aren't recognized
anymore. And if I try and compile this, you
| | 05:19 | will see I get lots and lots of errors.
| | 05:21 | If I hover over this, you will see it
says endl was not declared in the scope.
| | 05:26 | It's just not understanding these
symbols, and that's because the namespace is
| | 05:30 | not getting imported.
You'll see it this way a lot.
| | 05:34 | Instead of using namespace standard
like that, having namespace specified in
| | 05:39 | front of each of these tokens is very common.
| | 05:41 | So I am just going to show you we
will get into namespaces later on in the
| | 05:45 | course, and you will understand them a
lot better later, but you'll want to know
| | 05:49 | what this looks like because
you're going to see it sometimes.
| | 05:52 | So we are going to type STD for the
namespace and two colons, and that
| | 05:55 | specifies the namespace.
| | 05:56 | Then I am just going to copy and paste
that in front of endl as well, you will
| | 06:01 | notice that bug symbol went away.
| | 06:02 | I am going to do that on the next line
and the bug symbol went away, and when I
| | 06:09 | press Command+S here on this Mac or
Ctrl+S on a PC and save, and then I go up
| | 06:14 | and compile and run, see those Xs
go away and try running that again and
| | 06:19 | they come up on the separate lines.
| | 06:21 | So what was happening there, you see
now the red is on the bottom is that the
| | 06:25 | Hello, World to the standard out was
going out before the new line went out for
| | 06:30 | the standard errors.
| | 06:31 | So things like this happen sometimes
when you are mixing your streams, and it's
| | 06:35 | not unusual, and it's not unexpected.
| | 06:38 | So you'll see some strange behavior
when you are using both of these strings.
| | 06:42 | So now let's go ahead and delete and
Clean and then delete working.cpp, and I am
| | 06:49 | going to come up here to Project and
Clean and clean up our eclipse environment.
| | 06:54 | So that should give you a good introduction
to the standard output streams in C and C++.
| | 06:58 | We will take a quick look at the
standard input stream in the next movie.
| | Collapse this transcript |
| Using stdin| 00:01 | In C and C++ console applications, it's very common
to get user input from the standard input string.
| | 00:07 | Let's see how that works.
| | 00:09 | We will start by making a working copy of
working.c so I will copy that and paste it
| | 00:15 | into the Working project.
| | 00:17 | I am going to double-click on it
to open it in the Editor here.
| | 00:20 | The first thing we are going to do is we are
going to define a couple of constants and
| | 00:24 | these will be used later in the program.
| | 00:26 | I am going to use techniques here that we
haven't learned yet in this course and these
| | 00:30 | will be explained later in more detail.
| | 00:32 | I am going to start by declaring an enum. This
is a common technique for creating constant
| | 00:38 | integer values in C.
| | 00:40 | C++ has a better way to do this,
but in C, this is common.
| | 00:44 | So I am going to just call this one max_length
and I am going to give it a value of 127, and
| | 00:49 | then I am going to declare a static character
string, let's call it static char and we will
| | 00:58 | call it response and give
it a size of max_length.
| | 01:03 | Come down here to the printf and I am going
to just change this to give us a prompt, it
| | 01:06 | will say Type a sting.
| | 01:08 | And you notice it has a space there and no
new line, and that allows the prompt to sit
| | 01:14 | there and just have the cursor waiting at the
end of the prompt rather than on the next line.
| | 01:19 | But because this is using the standard output
string that string needs to be flushed before
| | 01:25 | we go waiting for input, otherwise there is
a chance that the prompt won't get printed
| | 01:30 | until after the input is
gathered, that's not we want.
| | 01:33 | So we use the fflush function like that
and we specify the standard output string.
| | 01:40 | And that flushes the standard output
string so that, that prompt displays.
| | 01:44 | Now we can go ahead and use fgets to get a
response from the console and that looks like
| | 01:49 | this. Fgets takes these three arguments, the
first one is the variable where the result
| | 01:56 | will be stored, the second one is the size of
that variable, the maximum length. In fact,
| | 02:03 | the fgets function will reserve
a byte for the null terminator.
| | 02:08 | So it will actually use max_length minus 1.
| | 02:11 | And then the third argument is the input
string to use which could be a file, it could be
| | 02:16 | a socket. In this case, we are using
standard input from the console.
| | 02:20 | So now that we have our response, we'll print it.
We will say printf, The string is, and we
| | 02:26 | use this %s token and that allows us to put
the value in there of our variable and we
| | 02:32 | will give that variable.
| | 02:33 | And I will save it with the Command+S key on
this Mac, you can use Ctrl+S on a PC.
| | 02:40 | And then we will come up here and press the Compile
and Run button and it's asking for the string.
| | 02:46 | Now the Console doesn't have focus, so I am
going to click on that with my mouse and now
| | 02:50 | the Console has focus and you see that my
cursor is right there where I want it. I just
| | 02:54 | type a string and I press the Return key and
you notice the string is this is a string,
| | 03:01 | so there is our response.
| | 03:02 | So there is a couple of important
things that you need to know about this.
| | 03:07 | You will notice that we are using the fgets
function. There is another function called
| | 03:11 | gets that is a common way to do this and I am
going to warn you right now never use gets,
| | 03:15 | always use fgets instead.
| | 03:18 | Gets was deprecated in C99 and
it's actually been removed from C11.
| | 03:23 | And the reason for this is that
it's a very insecure function.
| | 03:26 | It allows somebody to just type
too much and crash your computer.
| | 03:30 | By not limiting the size of the input, it
just blindly takes however many character
| | 03:35 | it's given and puts them into a
variable, but maybe too small for that.
| | 03:39 | It's a very, very common security hole.
| | 03:42 | And you are cautioned to never use the
gets function to always use fgets instead.
| | 03:47 | C11 actually defines a new function called
gets_s that may also be used, but as of the
| | 03:54 | time of this recording, this is not yet
supported by the Standard GCC Library and it's probably
| | 03:59 | not supported by very many libraries at all.
| | 04:02 | I strongly recommend that you just use
fgets for this. It's the right way to do it.
| | 04:07 | You may see other examples using the gets
functions, just don't ever do it yourself.
| | 04:11 | So this is how this is done is C.
| | 04:14 | Let's take a look at how this is done in C++.
| | 04:16 | I am going to go ahead and delete this
working.c from our Working project.
| | 04:22 | And we will copy working.cpp, copy that
and paste it and open it up in our Editor.
| | 04:33 | Now because of the object-oriented nature of
C++ and the fact that it has a very robust
| | 04:38 | string library, we don't need those constants at
the top, we can simply declare a string like this.
| | 04:45 | And then I can take this cout
and I can put in my prompt.
| | 04:50 | You notice that I have a colon and a space
just like I did in the C version, and here
| | 04:54 | for the flushing, I don't use the fflush
function, instead I am going to use this feature of
| | 04:59 | the C++ iostring library and I just put a flush
there like that with this Shift Left operator.
| | 05:06 | The string library overloads this shift left
operator. We will talk about this a lot more
| | 05:11 | in detail later on.
| | 05:13 | But just to understand this is how you
do something like this with a flush.
| | 05:17 | And now we can go ahead and get our input
and we do this with cin and we use the Right
| | 05:23 | Shift operator and we give
it the name of our variable.
| | 05:28 | Now we output our result.
| | 05:30 | And I am going to use another feature of the
iostring library and this is endl; endl does
| | 05:37 | a flush and then a new line.
| | 05:40 | And so it does both of those in one.
| | 05:43 | It's effectively the same
as if I have done this.
| | 05:46 | And so instead you can just do all of that
in four little characters like that, very
| | 05:51 | common. You are going to see this a lot.
| | 05:53 | And so I will save this and press the Compile
and Run button and you see down here we have
| | 05:59 | a little prompt. I am going to put my cursor
in the Console and click, so it gets focused
| | 06:04 | and I am going to type, this
is a string and press Return.
| | 06:08 | And you see our response this time says the
string is this and it doesn't have the last
| | 06:15 | three words. It just has the first word.
| | 06:17 | The reason for that is the cin function.
| | 06:21 | The cin function is designed to get just the
first word of a response, not the full response.
| | 06:28 | If you want to get the full response, the
best way to do that is with a function called
| | 06:33 | getline and it looks like this.
| | 06:37 | The getline function doesn't work like some of these other
string functions with the overloaded shift operators.
| | 06:42 | Personally, I like it better like
this. I think it's more clear.
| | 06:46 | And so now when we compile and run, I have
saved already with my Command+S key and I
| | 06:50 | will type a string and press Return.
| | 06:54 | And now we get our full response.
The string is this is a string.
| | 06:58 | So this is actually a lot simpler in C++.
We don't have to create a buffer, we don't
| | 07:03 | have to worry about the size of the buffer,
all that's done for us with the string library
| | 07:07 | and the iostring library.
| | 07:10 | That's how you get input from the standard input
for your Console applications in both C and C++.
| | 07:15 | Now we'll go ahead and delete our working file
and run Clean to get ready for the next lesson.
| | 07:22 |
| | Collapse this transcript |
|
|
3. The C Programming LanguageExploring the anatomy of a C program| 00:00 | As we begin learning about C, let's
take a look at a minimally valid C program.
| | 00:05 | In the Chap03 folder of your Excise
Files, you will find hello.c. Just copy
| | 00:10 | that and paste it into Working Project and
double-click on it, and this is a minimal C program.
| | 00:18 | It's actually not the smallest most
minimal possible legal correct C program,
| | 00:24 | but it is the smallest practical
example of a correct C program.
| | 00:30 | Let's take a look at all
of the different components.
| | 00:32 | In the first line here, we have a comment,
and you will notice that this comment
| | 00:35 | is introduced by the double slash .
| | 00:38 | This is actually a syntax that was
borrowed from C++ and was added to the C
| | 00:42 | Standard with C99, but it's commonly
used, and it has the advantage that if you
| | 00:48 | come out to the end of a line, and you
want to put just a comment to the end of
| | 00:51 | the line, you can do it that way,
instead of using the old syntax which would
| | 00:55 | have been to have a slash and an
asterisk and then another asterisk and a slash
| | 01:00 | at the end of the comment.
| | 01:02 | Now the advantage of the old style C
comments is that you can actually have your
| | 01:07 | comment span multiple lines, so you
can have it go on and on and on like that
| | 01:12 | and just introduce it with the
beginning comment marker and add the ending
| | 01:16 | comment marker at the end of it.
Each style has its advantages.
| | 01:20 | I tend to like the // version, // to
the end of the line, it's simple, and it's
| | 01:25 | quick and most of my
comments are just one line anyway.
| | 01:29 | The next line is actually a
preprocessor directive, and we'll get into the
| | 01:33 | preprocessor in our next chapter.
| | 01:34 | But this one includes a file,
and it includes this file in place.
| | 01:38 | So this file, called stdio.h which
sometimes simply pronounced standard I/O, the
| | 01:45 | entire file will be included in the
compilation process in this place, and that
| | 01:50 | allows us to have all our function
declarations for the standard I/O functions
| | 01:54 | from the standard library.
| | 01:56 | Next, we have the
declaration of the main function.
| | 01:59 | The main function is reserved in C.
| | 02:02 | All C programs must have a main
function, it's where execution begins.
| | 02:07 | So it is required, it is not optional.
| | 02:10 | Correctly, the main function should
return an int and so you see that first word
| | 02:14 | int that declares the
return type for the function.
| | 02:19 | And you notice we have a return
statement that says return 0, and that 0 is the
| | 02:24 | int that's been returned by this function.
| | 02:26 | After the word main you have
parentheses and inside of those parentheses, are
| | 02:31 | declarations of variables.
| | 02:33 | These are the variables that
will be used for parameters.
| | 02:36 | When parameters pass this function, they
will be copied into these variables and
| | 02:39 | those variables become accessible
inside the body of the function.
| | 02:43 | Then there is an opening curly brace, and
there is a closing curly brace on line 7.
| | 02:48 | Those mark off the beginning and the
ending of the block of code that is
| | 02:52 | the body of the function and inside the
body of this function, we have two statements.
| | 02:57 | The first statement is a function call,
calling a function called printf, and
| | 03:01 | you know it's a function call
because it's got a name and parentheses and
| | 03:04 | something inside of the parentheses.
| | 03:07 | And the next statement is the
return statement with the 0.
| | 03:10 | Both of these statements are terminated by a
semicolon, and that semicolon is not optional.
| | 03:16 | In C, all statements must be
terminated by a semicolon even if it's the last
| | 03:20 | statement in a block.
| | 03:21 | In a lot of languages, a semicolon can
be omitted as the last statement of a
| | 03:25 | block, it makes the semicolon more
of a separator than a terminator.
| | 03:29 | In C, it's a terminator and all
statements must be terminated by a semicolon.
| | 03:33 | If I remove this semicolon from the
return statement, then you will notice we
| | 03:37 | get a syntax error, says right there
Syntax error and so that semicolon is
| | 03:41 | required, and it is not optional.
| | 03:44 | So let's go ahead and compile this and
run it, and I'll press this Run button up
| | 03:48 | there, and you see the printf
function displaying the string Hello, World!
| | 03:53 | That's the argument to the printf function.
| | 03:55 | Now another thing you need to know
about C is that all this white space is
| | 03:59 | really just there for decoration.
It makes the program readable.
| | 04:03 | In other words I can get rid of these
indents, and it will still run just fine.
| | 04:08 | I can put these curly braces on a
separate line, and it runs just fine.
| | 04:13 | In fact, I can get rid of all of
the white space except in a few places
| | 04:18 | where it's required.
| | 04:19 | Obviously, it's required between the
return and the 0, because otherwise it
| | 04:23 | would be no way to know that these are
two different tokens, likewise between
| | 04:26 | int and main, but everyplace else, well,
we need it between int and argc but we
| | 04:31 | don't need this one.
| | 04:33 | And we don't even need these, and we
don't need that one, and we don't even need
| | 04:37 | that white space there.
So this is a perfectly valid C program.
| | 04:42 | I am going to save that, and we'll compile
it and run it, and you see it runs just fine.
| | 04:47 | Of course, this is not very readable.
| | 04:49 | So the reason we have all of these spaces
and the indents is to make the code readable.
| | 04:56 | Now there are different styles of doing this.
| | 04:58 | Some people like to put the curly
braces on lines by themselves, some people
| | 05:01 | like to indent one or both of the curly braces.
| | 05:05 | Whatever style you choose just be
consistent that style, there is no one right way.
| | 05:10 | Of course, if you work with other people,
it's often times useful for everybody
| | 05:15 | to agree on a particular
style and to stick to that style.
| | 05:18 | I tend to use the old K&R style
because it's the first one that I learned
| | 05:22 | from the original C programming book
that came out in the 70s by Kernighan
| | 05:26 | and Ritchie, often called K&R. So I tend to use
a style like that which is what you see here.
| | 05:31 | But it's not the best. There is no best.
| | 05:34 | The only thing that matters is that
you are consistent, and that you use the
| | 05:38 | same style consistently so that you
can read your code and so that other
| | 05:41 | people can read your code.
| | 05:43 | Now because C++ is based on C,
its syntax is basically the same.
| | 05:47 | Let's take a look at a C++
version of this program.
| | 05:50 | So I am going to go ahead and delete this
from the Working Project, and I will run Clean.
| | 05:57 | We'll take the hello.cpp, copy that and
paste it into Working and double-click.
| | 06:05 | And here we have the hello.cpp
version of this that's in C++, and I'll just
| | 06:10 | run it, and you see it does exactly the same thing,
and there are a few distinct differences.
| | 06:15 | You'll notice that the include directive
includes something called iostream, and
| | 06:18 | it does not have a .h at the end.
| | 06:21 | It's traditional for C++ include files
to not have the .h. You will also see a
| | 06:26 | line called using namespace std.
| | 06:28 | Namespaces are a concept that is in C++
but not in C, and we'll learn about
| | 06:33 | namespaces later on in the course.
| | 06:36 | But suffice it to know at this point
that the objects in the standard library,
| | 06:42 | the C++ standard library are
all in the standard namespace.
| | 06:47 | So this cout is actually
in the standard namespace.
| | 06:50 | If I take out that line that says using
namespace std, then I need to declare,
| | 06:55 | you see I get a syntax error
there, Symbol could not be resolved.
| | 06:58 | Then I need to declare that cout is in
that namespace, and I do that like this,
| | 07:02 | std::, and that declares that
cout is in that standard namespace.
| | 07:08 | Now if I save it and run it,
it continues to run fine.
| | 07:11 | I am just going to click this Run in Background.
| | 07:14 | So I tend to have the using namespace
line towards the beginning of all of
| | 07:19 | my examples in C++ because it makes
it easier, I can just type cout instead
| | 07:24 | of std::cout, especially if there is
a lot of objects in the code that use
| | 07:29 | the standard namespace.
| | 07:31 | You will also notice that the text is
output with the cout object rather than
| | 07:36 | using printf and cout is an object.
| | 07:39 | So it's using an operator here, it's
actually overloading the left shift
| | 07:43 | operator in order to send
text to this output stream.
| | 07:48 | That's become a common thing for
input and output streams and actually
| | 07:51 | the iostream library does that a lot with
the various input and output stream classes.
| | 07:56 | In fact, you can use printf if you like,
and I'm just going to put that in here
| | 08:01 | instead say printf and call the printf function.
| | 08:06 | Even though in the GCC library,
printf is declared in iostream, and it's
| | 08:11 | actually even declared
in the standard namespace.
| | 08:13 | It's more common when you are using
printf to go ahead and include the stdio.h
| | 08:18 | file or its C++ equivalent.
| | 08:23 | So C++ equivalents of .h files have a
c at the beginning and no h at the end
| | 08:29 | to designate that they are part of the C
standard library and not the C++ standard library.
| | 08:34 | And then I no longer need this using
namespace, so I can comment that out.
| | 08:37 | I can save this and run it, and you
will notice that we're basically
| | 08:42 | running exactly the same program that
we had in the .c file but we are running
| | 08:46 | it in .cpp file when
compiling it with the C++ compiler.
| | 08:51 | So it is possible because the entire C
language is included in C++ to simply
| | 08:57 | write C programs in a C++ file.
| | 09:01 | Obviously, if you have C++, it's a
good idea to make use of its various
| | 09:06 | features, but it's also good to know that
your regular C code will run just fine in C++.
| | 09:12 | So let's go ahead and delete this file
and clean it up, and Project > Clean, and
| | 09:18 | now we are all clean for the next lesson.
| | 09:20 | So that's the basic syntax of
a minimal C and C++ program.
| | 09:25 | We'll get into more of the
details later in this chapter.
| | Collapse this transcript |
| Writing statements and expressions| 00:00 | The C programming language consists
mostly of expressions and statements.
| | 00:04 | In fact, many statements are
also expressions and vice-versa.
| | 00:08 | Let's make a working copy of working.c
from the Chap03 folder in the exercise
| | 00:14 | files, paste it into the Working
Project and double-click to open it.
| | 00:18 | And this is our simple Hello, World! program.
| | 00:21 | So, if I press the green Run, it will
compile it and run it, and it displays the
| | 00:26 | constant string Hello, World!
| | 00:28 | But what you may not realize is
that printf is also an expression.
| | 00:31 | It is a function that returns a value,
and that value can be assigned, it can be
| | 00:37 | calculated with, you can do
all kinds of things with it.
| | 00:39 | So let's assign it to a simple
integer variable here x =, printf returns an
| | 00:45 | integer value, so I can print
that with another printf statement.
| | 00:50 | So that's printf and the constant
string printf returned %d and \n which
| | 00:56 | represents a new line and then Comma
and the x variable so that x variable will
| | 01:03 | be used for the value of this %d. So it
will say, printf returned and a number,
| | 01:09 | and that number will be
the number returned by printf.
| | 01:11 | The value that printf returns is the
number of characters that it printed.
| | 01:15 | So in this case, there are five
characters in Hello, there are five characters
| | 01:19 | in World, you have a comma, a space and
a new line and an Exclamation Point so
| | 01:24 | that comes out to 14 characters.
| | 01:26 | So when I run this, Compile and Run,
see it says printf returned 14 because it
| | 01:32 | printed 14 characters.
| | 01:34 | Now in fact, because printf returns a
value that value can be used on the right
| | 01:39 | side of an expression as it is here in
assigning it to x, it can also be used on
| | 01:44 | the left side of an expression.
| | 01:46 | So I can say printf * 5.
| | 01:48 | So it will take that value 14, and it
will multiply it by five and display that.
| | 01:53 | So I am going to Save and Compile
and Run, you see, it returned 70.
| | 01:58 | Well, printf actually returned 14,
and then it got multiplied by 5.
| | 02:02 | But x here is now the value 70
because we've multiplied it by 5.
| | 02:08 | So in fact, the printf
statement is also an expression.
| | 02:12 | It calls a function, and that
function returns a value, and that value can
| | 02:16 | be used in calculations. It can be used on
the right or on the left side of an expression.
| | 02:21 | So, really most statements are
expressions, what makes an expression a statement
| | 02:26 | is the fact that it's terminated by a semicolon.
| | 02:28 | So this entire statement here is a
statement because it's terminated by a
| | 02:32 | semicolon, but it also includes a few
expressions, and this expression here,
| | 02:38 | even though we are not using the value
of it, it's still an expression, and it's
| | 02:43 | also a statement because
it's terminated by a semicolon.
| | 02:46 | So, very specifically, an
expression is a unit of computation.
| | 02:50 | An expression has a value.
| | 02:52 | That value can be void in some cases
which means that it can't be used, but
| | 02:56 | it's still a value.
| | 02:57 | A statement on the other hand is a
unit of execution and a statement is
| | 03:01 | terminated by a semicolon.
| | 03:02 | Multiple statements can be
grouped together with curly braces.
| | 03:06 | These are called Compound Statements.
They are also sometimes called blocks.
| | 03:09 | Unfortunately, the term block also has
other meanings, so you will need to be
| | 03:13 | careful of its context where
you see it and where you use it.
| | 03:16 | You can use a compound statement
anywhere where a statement is allowed, but they
| | 03:20 | are commonly used with control statements.
| | 03:21 | For example, I can put all
of this inside of a loop.
| | 03:24 | I can say for(int i = 1; i <= 5; ++i).
| | 03:33 | All of that inside of this block,
and I'll go ahead and indent those so
| | 03:37 | that we can see that they are inside the
block, but really it's the curly braces
| | 03:41 | that make that a block.
| | 03:43 | Now both of these statements will be
executed each time we iterate this loop.
| | 03:47 | So I'll save this, and we'll Run it,
and we see now this is getting run
| | 03:53 | five times Hello, World!
printf returned 70, Hello, World!
| | 03:57 | Five times, and that's because all of that
is inside of that block with the curly braces.
| | 04:03 | Keep in mind that the compound
statement here is really a convenience.
| | 04:07 | It allows you to have several statements in
place where normally you would have just one.
| | 04:11 | If I were to delete all of this and
just put one statement here--terminate that
| | 04:16 | with a semicolon. Now we have this
control structure, this for loop, and it has
| | 04:21 | just one statement so that one
statement will get run five times.
| | 04:24 | So I am going to Save that and Run it, and we
see i is 1, i is 2, i is 3, i is 4 and i is 5.
| | 04:33 | So that loop got run five times,
but it only has the one statement.
| | 04:36 | When there's just the one statement,
it's a single statement, so you don't need
| | 04:40 | the curly braces because it
doesn't have to be compound.
| | 04:43 | Although it is common practice, and
it's actually good practice when you have a
| | 04:47 | control structure to go ahead and
use a compound block anyway, even when
| | 04:53 | there's just one statement.
| | 04:54 | You notice that Eclipse put in
both of the brackets there for me and
| | 04:59 | indented and everything.
| | 05:00 | The reason you want to use the
braces in the compound structure even when
| | 05:03 | there's only one statement is if later
on you decide to add another statement,
| | 05:11 | you already have the braces,
and you already have the block.
| | 05:15 | Otherwise it's possible to forget that
and even though you indent it, not having
| | 05:19 | the braces, it won't be part of
that block, so it just prevents errors.
| | 05:23 | So I'll go ahead and Save this and Run
it, and you see that those all get run
| | 05:28 | together each time through the loop.
| | 05:29 | Statements and expressions are the
building blocks of the C language.
| | 05:32 | While statements are often also
expressions, understanding distinction is
| | 05:38 | important to becoming a proficient C programmer.
| | 05:41 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with identifiers| 00:00 | Identifiers in C are tokens used to
give recognizable names to variables,
| | 00:05 | functions, labels and defined types.
| | 00:09 | In C and C++ Identifiers consist of the
ASCII representation of the 26 letters
| | 00:15 | of the ISO basic Latin Alphabet, both in
lowercase and uppercase. The 10 Western
| | 00:23 | Arabic Numerals and the
ASCII Underscore character.
| | 00:27 | Identifiers may not begin with a number.
| | 00:30 | Identifiers may not
conflict with reserved words.
| | 00:33 | The current C language Standard C11
reserves 43 words, and the current C++
| | 00:40 | Standard C++11 reserves 73 words.
| | 00:44 | You cannot use any of
these words as an identifier.
| | 00:48 | Identifiers are case sensitive, so this Az on
the left is different from the aZ on the right.
| | 00:55 | So even though these both say Az
they are different identifiers.
| | 00:59 | Current standards allow letters
that are not part of the ISO basic
| | 01:03 | Latin Alphabet but support for this is
implementation dependent, and it is not portable.
| | 01:09 | I highly recommend you stick to the
26 letters of the basic Latin Alphabet
| | 01:13 | Numbers and the Underscore using
international character sets is not portable.
| | 01:19 | Current standards allow identifiers to
be of any length, although only the first
| | 01:23 | 63 characters are guaranteed to be
check for uniqueness and only the first 31
| | 01:29 | characters are guaranteed
for external identifiers.
| | 01:32 | So in practice you should keep your
identifiers under 31 characters long.
| | 01:36 | An initial Underscore character, that
is an Underscore in the first position of
| | 01:41 | an identifier is commonly
used for private identifiers.
| | 01:45 | More than one initial Underscore is
normally reserved for system-level private use.
| | 01:50 | So don't name your variables
with two initial underscores.
| | 01:54 | Like so many aspects of programming
it's a really good idea to decide on a
| | 01:58 | consistent style for choosing your
identifiers and stick to that style,
| | 02:02 | understanding the rules, choosing
conventions and sticking with them, will help
| | 02:06 | to make your code more readable
and maintainable for the long term.
| | Collapse this transcript |
| Defining variables| 00:00 | Variables are strongly typed in C,
that means that the token representing a
| | 00:04 | variable represents both its value and its type.
| | 00:07 | Let's make a working copy of working.c.
Copy and Paste and open it up in our
| | 00:14 | editor here, and I'm going to
go ahead and declare a variable.
| | 00:18 | I'm just going to say, int i; like that.
So this statement is a variable definition.
| | 00:23 | It defines the type of the variable, and
it allocates space of a size sufficient
| | 00:28 | to hold a value of that type.
| | 00:30 | This variable is an integer, currently
it has no assigned value, so it's said to
| | 00:35 | be undefined, and undefined variables
are dangerous thing, so be sure to always
| | 00:40 | assign a value to a variable.
| | 00:42 | So let's go ahead and
give it a value, give it 7.
| | 00:45 | A variable definition is also a
variable declaration, the distinction exists
| | 00:49 | only really for external variables,
and we'll talk about external variables
| | 00:53 | later on in this course.
| | 00:55 | Under many circumstances you'll both
declare and initialize a variable at
| | 01:01 | once like I have here, or we can do
something like that and declare and
| | 01:07 | define a character string.
| | 01:08 | Now once that character string is
declared and defined we can actually use it here.
| | 01:14 | And when I compile this it will
probably complain about i being unused.
| | 01:19 | Save it and Run it, and so we get a little
bit warning there, you see because i is unused.
| | 01:24 | That's a nice feature of Eclipse.
| | 01:26 | But here we have declared and defined
this variable, and we've initialized it
| | 01:30 | with the value of this
constant string, and we printed it.
| | 01:34 | So in C all variables must be
declared before they can be used.
| | 01:39 | In other words, if I didn't declare
and define it like that, and I try to use
| | 01:44 | it we get an error.
| | 01:45 | We can see Eclipse will give us that error
right away, Symbol 's' could not be resolved.
| | 01:50 | The fundamental types available for
variables are covered in more detail in
| | 01:53 | the Data Types chapter.
| | 01:55 | So now let's go ahead and delete and clean
so that we're prepared for the next lesson.
| | Collapse this transcript |
| Understanding identifier scope and using storage classes| 00:00 | Identifier Scope and Storage Class
determine when and where you may use an
| | 00:06 | identifier or a variable.
| | 00:07 | Let's make a working copy of working.c,
copy and paste it into the Working
| | 00:14 | project and double-click
to open it in the editor.
| | 00:17 | Scope refers to the places where
an identifier may be safely used.
| | 00:21 | For example, if an identifier is
declared outside of any functions or blocks,
| | 00:26 | it's visible from the place it was
declared until the end of the file.
| | 00:30 | So if I go ahead and declare an
identifier out here, and I have a variable
| | 00:34 | named number, and if I want to print
that inside of this function, I can say
| | 00:42 | save that and run it, sometimes we get this
launcher thing, and it says the number is 7.
| | 00:48 | Now on the other hand if I take this,
and I move that and put it after the
| | 00:54 | function where it's used, and if I
save that and try to compile it, we are
| | 00:58 | going to get an error.
| | 00:59 | And our Error here says number is
undeclared, because it's actually
| | 01:04 | declared after the fact.
| | 01:06 | So when an identifier is declared
outside of any functions or blocks, it's
| | 01:10 | visible from the place it was declared
until the end of the file, and here it
| | 01:14 | is not visible to this function, because
the function happens before the declaration.
| | 01:18 | So we'll go ahead and move that again, and
we're going to declare it inside the block.
| | 01:25 | Now it will be visible again because
it's declared inside of this same block
| | 01:30 | and before it's used.
| | 01:31 | So if I save that and run it, but if
I were to declare it inside the block,
| | 01:38 | but after where we are using it, now
we're going to get an error, see we've
| | 01:43 | already got this error showing up here,
if I try to compile it,
| | 01:46 | we have that problem again.
| | 01:48 | And if I were to declare it inside of
another block, let's say if(1), which is
| | 01:53 | always going to be true, and I'll just
declare that variable inside of there,
| | 01:58 | but it's inside of that block, it
will not be visible out here either.
| | 02:03 | Try and run that, and we get the same error.
| | 02:06 | And we also get an error
that it's an unused variable.
| | 02:09 | So that's called identifier scope.
| | 02:11 | It talks about the scope in which a
variable or an identifier is available.
| | 02:17 | Scope is not to be confused with storage class.
| | 02:20 | Storage class refers to when, where and
how the storage space for a variable is
| | 02:26 | allocated and deallocated.
| | 02:28 | Storage class is sometimes referred to
as storage duration, and there are four
| | 02:32 | distinct storage classes available.
Auto, static, extern and register.
| | 02:38 | Auto is the default storage class for
a variable defined inside of a block.
| | 02:43 | So here, for example, we've defined
this integer inside of this block, so its
| | 02:48 | default storage class is auto, which
means that it's allocated in temporary
| | 02:52 | space, and so here we'll save this, and
we'll run this, and we see that it works
| | 02:58 | fine, and this is an auto variable.
| | 03:00 | So the space that variable is actually
allocated at that time inside that block,
| | 03:05 | and it's deallocated at the end of the block.
| | 03:08 | Now let's put all of this inside of
a loop, so we can take a look at the
| | 03:12 | difference between auto and static
storage duration, for(int i = 1; i <= 5; ++i)
| | 03:25 | and we'll go ahead and close the
block here and indent it for clarity.
| | 03:29 | So now the interesting thing here is
that when I save this and run it, you see
| | 03:33 | we just have the number is 7 five times.
| | 03:36 | If I increment that, I'll just put a
plus, plus after it, so now it gets
| | 03:43 | incremented each time, but it's still
going to be the number is 7 five times,
| | 03:47 | because it's auto storage,
it goes away each time.
| | 03:51 | On the other hand, if I make this static,
say static int number = 7, now it's no
| | 03:58 | longer auto storage, every time
through the loop it's using exactly the same
| | 04:01 | storage space and so when I run it, it
actually gets incremented, it starts at
| | 04:05 | seven and goes up 8, 9, 10, 11.
| | 04:07 | That's now static storage, it's permanent,
it stays there, and it can be reused.
| | 04:12 | We are going to skip extern storage
for a moment, and we are going to talk
| | 04:17 | about register storage.
| | 04:18 | If I say register here, you'll see
that it works just like auto, so I'll
| | 04:21 | save that and run it.
| | 04:23 | You see it says the number
is 7, the number is 7 seven.
| | 04:26 | The distinction here is that you're
giving the compiler a hint to try to store
| | 04:29 | this variable in a register of the
processor rather than storing it in temporary
| | 04:35 | storage space, and this should make it faster.
| | 04:38 | The reality is is if you are using any
optimization in your compiler anyway, the
| | 04:43 | register keyword is
probably going to be ignored.
| | 04:45 | And the optimizer is going to choose
variables that are used in certain ways and
| | 04:51 | put those in registers if it can
to make them really, really fast.
| | 04:54 | So, even though this keyword exists, it may
or may not be implemented in certain ways.
| | 04:59 | Modern optimizers are usually better at
this than the programmers, so it's best
| | 05:03 | to use this only where
it's absolutely necessary.
| | 05:06 | Now let's talk briefly about extern.
| | 05:09 | What I am going to do here is I am
going to grab this func.c, and I am going to
| | 05:12 | copy and paste that into our Working space.
| | 05:16 | I am going to open that up, and now we
have two files open, we have func.c and
| | 05:20 | working.c. We have a problem here, we
have this func.h, I am going to delete
| | 05:25 | that, I am also going to delete this
main because we're not going to use that.
| | 05:29 | And so what we have here is we have
a function called func, and I'm going
| | 05:33 | to just also declare variable int,
I am going to call it var, and I am
| | 05:37 | going to give it a value 47.
| | 05:40 | Because these are in the same folder,
and we're using Eclipse, this will go
| | 05:44 | ahead and get compiled and linked
together with our working.c. And so I can
| | 05:48 | declare up here, I can say extern func
and what's my function, it's just a void.
| | 05:54 | So I am going to say extern void func like
that, and then I can call it from right here.
| | 05:59 | I can say func, and it will get called.
| | 06:02 | And if we look over what it does, it
just printfs, this is in the function.
| | 06:06 | And when I save that and run it,
you'll notice that this is the function,
| | 06:11 | because that's what in our function
over there so that got actually run.
| | 06:15 | If I take out this extern void func
declaration and try to run it, you'll notice
| | 06:22 | that we get an error right here,
implicit declaration, and that's not allowed.
| | 06:28 | So put that extern void func back in.
| | 06:31 | So the external storage class means
this is something that's in a different
| | 06:34 | translation unit, it's in a
different source file, and it gets linked
| | 06:38 | together at link time.
| | 06:39 | So this tells the compiler don't
worry about it, we'll link that together
| | 06:43 | when we do the linking.
| | 06:44 | So, I am going to save that and run
it, and that should get rid of our
| | 06:49 | little error thing there.
| | 06:50 | We can do the same with the variable,
I can say extern int var, and now I can
| | 06:54 | actually print that, I can come down here,
and I can say printf extern var is %d
| | 07:03 | and a new line and var.
| | 07:05 | And that will actually you see this
variable over here is number 47 so that will
| | 07:09 | actually go ahead and print that.
So it's the extern var is 47.
| | 07:14 | So this external storage class extern,
it tells the compiler this is something
| | 07:20 | that's defined elsewhere, but we're
declaring it here because we're going to
| | 07:24 | use it here, but it's actually defined in a
different file, in a different translation unit.
| | 07:29 | So scope refers to where an identifier
is visible and storage class refers to
| | 07:34 | how and where the storage is
allocated for the identifier.
| | 07:37 | Understanding these concepts is important for
writing code that is efficient and reliable.
| | 07:43 | Now let's delete our working files and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Declaring variables and functions| 00:00 | Before identifiers can be
used they must be declared.
| | 00:03 | In early versions of C all the
declarations needed to be at the top of the block
| | 00:07 | of code, but in version since ANSI C or
C89 this restriction has been removed.
| | 00:13 | It's now considered good practice to declare
variables closest to where they are first used.
| | 00:18 | Let's make a working copy of func.c,
paste it here into the Working project,
| | 00:24 | and I'll open that up.
| | 00:26 | I'm going to go ahead and comment out
this #include directive for now, we'll
| | 00:29 | be using that later.
| | 00:30 | I'll go ahead and Compile and Run it,
and you can see it displays Hello, World!
| | 00:34 | And then it calls this function
which prints, this is in the function.
| | 00:39 | So in this case we have declared and
defined the function before it's used.
| | 00:43 | We're using the function in main, and
that's on line 11 and up here in line 5,
| | 00:49 | the function is being declared and defined.
| | 00:52 | If we move that definition down after
the main function, and we go ahead and
| | 00:57 | Save this and Compile and Run it, you
see our compilation. I'm going to go ahead
| | 01:02 | and press this button over here which
changes the Console to show the compilation process.
| | 01:07 | You see that there are warnings in here,
and we can see those warnings also in
| | 01:12 | these little Exclamation markers.
| | 01:13 | And so that's not really working as we
expected it, it's kind of working by accident.
| | 01:19 | If we go ahead and declare this
above here, let's say void func() with a
| | 01:24 | semicolon, like that. That's just a
declaration it's not a definition, and we save
| | 01:29 | this and Compile it and Run it.
| | 01:32 | Now our warnings go away and
everything is working as we expected it.
| | 01:36 | So the declaration, even though the
definition can be later or the definition
| | 01:39 | can be even in an external translation
and linked later, that declaration needs
| | 01:44 | to be before it's used.
| | 01:46 | The same is true of course, of variables,
I can say int i = 47 up here, and then
| | 01:52 | I can come inside my printf, and I can
just say, i is %d, and i there, and that
| | 02:01 | will work exactly as I expected it to.
See now here it says i is 47.
| | 02:07 | And if I were to move that to after
main and try to Compile and Run it, we
| | 02:13 | actually get an error.
| | 02:15 | This is not just a warning because it
doesn't even know what to do with the i.
| | 02:19 | It's also common to declare it inside
of the function, this main function here,
| | 02:24 | I can save this and Compile and
Run it, and that works just fine.
| | 02:28 | And I can move both of these later in
the function even after the function call
| | 02:34 | and Compile and Run that,
and that works as expected to.
| | 02:37 | This is the thing that didn't used to
be legal in C before C89 that would have
| | 02:43 | had to have been at the top of the function.
| | 02:45 | So oftentimes you'll see just as a
matter of tradition a lot of declarations
| | 02:49 | at the top of a function and then those
things are all used later on in the function.
| | 02:53 | And that's really a throwback to the
early days of C, and it's not really
| | 02:57 | considered best practice anymore, best
practice is considered today to declare
| | 03:01 | something just before you use it and
perhaps set off that bit of code with some
| | 03:05 | new lines like that.
| | 03:07 | I'll go ahead and Compile and Run that,
and we see that it works as expected.
| | 03:12 | Another common paradigm is to have a
for loop and inside the for loop control
| | 03:18 | you have a variable that's just use for
loop control, so you can say (int i = 0; i < 5; ++i)
| | 03:26 | increment i and then put this all in
a block, and we can take this printf,
| | 03:32 | and we can put that inside the block,
and now that will happen five times.
| | 03:37 | And so I'll compile and Run that,
and we see that i is 1, 2, 3, 4, 5.
| | 03:42 | Now here I reused i because I had
named my variable i up above there as well,
| | 03:47 | and so this one is getting unused because
I have one defined inside this other scope.
| | 03:53 | So I'll get rid of that for now.
| | 03:55 | This construct here of both defining
and declaring the variable inside of those
| | 04:02 | parentheses that used to be illegal,
you used to have to declare the variable
| | 04:08 | outside like this and then
initialized inside the loop construct like that.
| | 04:14 | We'll see that runs exactly as we
expected to, and so you'll often see that.
| | 04:18 | But since C99 the second to latest
standard we've been able to do it this way
| | 04:26 | which is a lot cleaner.
| | 04:28 | And as we've seen our functions need
to be declared as well, so here we have
| | 04:31 | this void func() at the top.
| | 04:34 | It's often very common instead to put
that inside a header file and include that
| | 04:39 | using a Preprocessor directive like this.
| | 04:41 | So let's go ahead and copy and paste
func.h from the Chap03 folder and paste
| | 04:46 | that into our Working project.
| | 04:48 | We'll go ahead and open that up, and you
see in here we have that function declaration.
| | 04:53 | And so, by including it here then it's
actually included in the scope, because
| | 04:58 | remember that included
file gets included in place.
| | 05:02 | This entire #include directive gets
replaced with the contents of that file.
| | 05:07 | We'll discuss later the distinction
between these quote marks and these brackets
| | 05:10 | when we'll talk about the preprocessor.
| | 05:13 | But for now know that everything
that's inside of this file is actually get
| | 05:17 | included in this context.
| | 05:18 | So when I save this and run it, our
function call happens fine, we don't get the
| | 05:22 | warnings even though the
function is defined down here.
| | 05:26 | So inside the header file we have the
declaration and inside the source file we
| | 05:32 | have the definition.
That's an important distinction.
| | 05:36 | So variables and functions must be
declared before they can be used, they may be
| | 05:40 | declared in header files, even
defined in external source files that are
| | 05:45 | compiled separately and linked later,
but they must always be declared in scope
| | 05:49 | before they are used.
| | 05:52 | Now let's delete our working files run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using pointers| 00:00 | Pointers are very powerful, useful,
dangerous and common construct in C.
| | 00:06 | To truly understand pointers you must
first understand how variable works.
| | 00:10 | A variable is a typed and
named location in memory.
| | 00:14 | In this declaration memory is
allocated in the size of an integer and
| | 00:18 | associated with the name x.
| | 00:20 | Here the integer value 1 is placed in
the memory location associated with the
| | 00:25 | integer variable x, and this is both a
declaration and an assignment, memory is
| | 00:30 | allocated in the size of int and the
value from the variable x is copied into
| | 00:35 | the variable named y.
| | 00:36 | The variable y now contains a separate
integer in a separate memory location
| | 00:41 | with the same value as the variable x.
| | 00:44 | So we can see that the name of a
variable is used as an index to map to a memory
| | 00:49 | address and a particular associated data type.
| | 00:52 | C syntax gives you the ability to create
a variable that is a pointer to a value
| | 00:57 | as opposed to carrying the value itself.
This is a pointer declaration.
| | 01:02 | The variable named ip is of
the type pointer to int.
| | 01:06 | Here memory is allocated in a sizable
pointer and the Compiler associates this
| | 01:11 | pointer with the type int.
| | 01:13 | This is typically referred
to as an integer pointer.
| | 01:17 | Here the address of x is placed
in the pointer variable named ip.
| | 01:22 | The Ampersand is formally called the
Reference Operator, but is more commonly
| | 01:26 | called the address of operator.
| | 01:28 | It returns the address of an object,
suitable for assigning to a pointer.
| | 01:34 | So this statement assigns the
address of x to the integer pointer ip.
| | 01:39 | The integer pointer ip now
points to the integer variable x.
| | 01:44 | It's worth noting that the Ampersand is
also used in C++ for special reference
| | 01:49 | type that is not available in C.
| | 01:50 | The reference type is covered
later in the Data Types chapter.
| | 01:54 | This statement copies the value pointed
to by ip which currently points to the
| | 02:00 | integer variable x to the integer variable y.
| | 02:03 | You can of course change ip to
point to a different variable.
| | 02:07 | Understanding pointers is
critical to using C or C++ effectively.
| | 02:11 | Take some time to go through these
examples and experiment with pointers on your
| | 02:14 | own, understanding this will
serve you well for the long-term.
| | Collapse this transcript |
| Working with arrays and strings| 00:00 | Arrays are simple to
define and simple to use in C.
| | 00:04 | This declares an array of
integers with room for five values.
| | 00:09 | Arrays are indexed with integer values.
The first element is always number 0.
| | 00:15 | This assigns the value 1 to
the first element of the array.
| | 00:20 | This declares an integer pointer
and assigns the address of the array.
| | 00:24 | Notice that you don't need to use the
ampersand address of operator to assign
| | 00:28 | an array's address.
| | 00:30 | This is a special case in C syntax, and it's
worth remembering because it's used frequently.
| | 00:35 | The name of an array may be used as an
address without the ampersand address of operator.
| | 00:42 | This assigns the value 2 to the first
element of the array, because the pointer
| | 00:47 | was assigned to the array, it
is pointing to the first element.
| | 00:51 | You can increment the pointer, and
it will point to the second element.
| | 00:56 | In C pointers are strongly typed.
So they know the size of what they point at.
| | 01:00 | So when you increment a pointer it always
increments by the size of the object it points to.
| | 01:04 | So this assigns the value 3 to
the second element of the array.
| | 01:09 | This is another common technique in C.
| | 01:11 | Here we're incrementing pointer
and using it at the same time.
| | 01:15 | It's just a shortcut for the
separate increment and assignment of the
| | 01:18 | previous two statements.
| | 01:21 | In C a string is a special case of an array.
To illustrate let's look at an example.
| | 01:28 | Let's make a copy of working.c, and I'll
copy that and paste it into the working
| | 01:33 | project and double-click to open it up.
| | 01:36 | I am going to start out by
declaring an array of characters.
| | 01:40 | So I'll say char s and just the two brackets.
| | 01:44 | We're not going to put a number in for
the size of the array, because that can
| | 01:49 | be inferred by its initialization.
| | 01:50 | Here we're going to initialize it with
a number of characters 's', 't', 'r',
| | 01:58 | 'I', you see where I'm going
with this? The 'n' and a 'g'.
| | 02:01 | Then I am going to give it a number 0
and a semicolon, and this is a c-string.
| | 02:07 | In C a string is simply a
special case of an array.
| | 02:11 | It's array of characters, and
it's terminated by a 0 value.
| | 02:15 | Some people call that a null terminator.
| | 02:17 | So this null-terminated array of
characters is exactly the same as string.
| | 02:23 | In fact, I can do this.
I can say string is:
| | 02:28 | %s and give it the s variable
which is an array of character that we've
| | 02:33 | initialized right there.
| | 02:34 | And give this all to printf,
and it will print the word string.
| | 02:38 | I'm just going to save that and run it.
| | 02:41 | It's compiles it and runs it,
and it says string is string.
| | 02:44 | So this is exactly the same as if we
had done this, which is of course the more
| | 02:49 | common way to do that.
| | 02:51 | So this simply initializes this
character array with the letters s, t, r, i, n,
| | 02:57 | g, and the null byte the 0 value.
| | 03:00 | So this array is seven characters
long, and it holds the string string.
| | 03:05 | So if I run this we get exactly the same result.
| | 03:08 | In fact, we can treat this as a string.
| | 03:11 | We can say for (int i = 0; s left bracket
i right bracket != 0; ++i).
| | 03:21 | We can just print out each character.
| | 03:26 | %c will print a character, and we are
going to say s sub i, which is actually of
| | 03:32 | type character, and now when I save this and
run it, see we get all of the individual characters.
| | 03:39 | Here they are, s, t, r, i, n, and g.
| | 03:42 | So we can see that a string is really just
a special case of an array of characters.
| | 03:47 | And that character pointer should index
into that array just as we would expect.
| | 03:52 | So we can actually do something like
this instead of using the integer to index
| | 03:57 | in the array I can declare a
character pointer like this, initialize it to
| | 04:01 | point at the array.
| | 04:02 | Remember, you don't need to use the
address of operator with an array, and I can
| | 04:07 | say, while, what is pointed at by cp.
| | 04:09 | I don't even really need to compare it,
and I don't need to do not equal to
| | 04:14 | zero, because I can
actually use it as a logical value.
| | 04:17 | This is very common in C, and increment
the character pointer, and now instead
| | 04:22 | of this s sub i, I can just do that.
| | 04:25 | So here I'm using this character
pointer to index through this array.
| | 04:29 | I'm using it like an iterator, and that's
really a very, very common paradigm in C.
| | 04:34 | So I save this and run it, and you
see we get exactly the same result.
| | 04:38 | There is our character
string s, t, r, i, n, and g.
| | 04:42 | So the combination of arrays and pointers
is really powerful and really common in C.
| | 04:47 | Array is a structure variable of the same type
stored contiguously indexed by an integer value.
| | 04:53 | Because the array is guaranteed to be
stored contiguously it's also easy to
| | 04:57 | iterate it with pointers and C
syntax lends itself well to this usage.
| | 05:02 | So let's delete the Working file and run
Clean to get set up for the next class.
| | Collapse this transcript |
| Comparing with conditionals| 00:00 | The C language has two
basic forms of conditionals.
| | 00:03 | The if else control structure,
and the conditional operator.
| | 00:08 | Let's take a look at this.
| | 00:09 | Make a working copy of working.c,
paste it here into our Working project,
| | 00:15 | double-click on it to open it up,
and we'll just replace that printf with
| | 00:20 | a control structure.
| | 00:21 | We'll start with if and a couple variables
for true and false int a = 1 and int b = 0.
| | 00:31 | In C++, you have a bool type for
booleans, and you have true and false.
| | 00:36 | In plain old C, you've
got integers, and 1s and 0s.
| | 00:40 | Of course you can use any of these
scalar integer types, you can use character,
| | 00:45 | you can use int, you can use long,
int is really common, it's usually a
| | 00:49 | convenient word size usually don't actually
save any space or any speed by using a char.
| | 00:54 | You can use a char here,
and it'll work just as well.
| | 00:57 | I'm going to use ints for now.
And so 1 is true and 0 is false.
| | 01:02 | So we're going to say, if(a), we'll use a
puts here, because we're not going to be
| | 01:08 | doing these substitution, "this is true".
| | 01:10 | So if I save this and run it,
we'll get this is true.
| | 01:15 | And if I change that a to a b, save
that and run it then we'll get nothing
| | 01:20 | because it's not true.
So let's put in an else clause.
| | 01:23 | We can say else puts ("this is
not true") and save that and run it.
| | 01:31 | And now for b, it's not true, and if
we put the a back in there and save that
| | 01:36 | and run it, we get this is true.
| | 01:38 | So that's pretty straightforward, and
of course the common way to see this, and
| | 01:42 | I personally will rarely just put a
statement on the same line as a conditional
| | 01:47 | like that, that's an invitation to bugs.
| | 01:49 | I mean, it works, and it's correct, and
if you never change it, it's fine, but
| | 01:54 | the minute you start messing
with it, you tend to make mistakes.
| | 01:57 | So always just put it in the curly
braces like that, and do the same thing here.
| | 02:02 | And I will usually also put the else on
the same line as the closing curly brace
| | 02:07 | of the if, that's called a cuddled else.
And a lot of people hate that, I like it.
| | 02:12 | I find it really easy to read, and I
find that it's economical on space, and so
| | 02:16 | this has exactly the same result here.
| | 02:18 | We'll run that, and it says this is true,
and if we change it to a b and save it
| | 02:23 | and run it, we get this is not true.
| | 02:26 | You notice we get the little warning
here for the variable we're not using as an
| | 02:30 | unused variable, and that's
fine, we were expecting that.
| | 02:32 | Now what if you want to test for if that's
not true, let's see if the other one is true?
| | 02:37 | A lot of languages have an elseif,
where you can do something like that.
| | 02:41 | I'll change this one to a and then
test for b and the elseif, unfortunately C
| | 02:47 | does not have an elseif.
| | 02:48 | So you have to actually do this here,
and say else if as two words, and it
| | 02:53 | works exactly the same.
| | 02:55 | So if I run this, I say this is true,
and if I make this one a 0, and this one
| | 03:02 | a 1, then I get the else if b, and I can
actually put there, the other is true and run that.
| | 03:11 | And then if you want, you can have
final else, and say, nothing is true.
| | 03:16 | And then if I make both of these 0s,
then I get the nothing is true.
| | 03:21 | This is a really, really common you
know, sometimes you'll get chains of
| | 03:25 | else ifs and else ifs and then an else at
the end, it's a pretty common way to do things.
| | 03:30 | C also has another way of doing
conditionals, and this is called the
| | 03:35 | ternary conditional operator just because
it's so much fun to say, and it works like this.
| | 03:44 | So if a is true, we'll get a seven in c,
and if a is not true then we'll get a 9, okay?
| | 03:50 | So I'll go ahead and I'll say printf("c is %d\n
", c) and save it and run it, it says c is 9.
| | 03:59 | So what it does here is it tests the
condition, and if the condition is true,
| | 04:03 | it gives you the first value, and if the
condition is not true, it gives you the second value.
| | 04:08 | So in this case, it's not true because
both of these are 0s at this point, so we
| | 04:12 | get a 9, and if I change the a to a 1
and save that and run it, then we get a 7
| | 04:18 | because that condition is true.
| | 04:19 | And so, you can do things like you can
say if a == 5, save that and run it, then
| | 04:27 | I get 9, because it's not equal to 5.
| | 04:29 | If I make it a 5, then I save it and run it,
then we get the 7 because it's now true.
| | 04:35 | So it's called the ternary conditional
operator because there is a condition,
| | 04:39 | which is this part here, and it's
really always a good idea to put this in
| | 04:43 | parentheses, because otherwise you
need to memorize the operator precedence
| | 04:47 | chart, and nobody enjoys doing that.
| | 04:49 | And if you have anything more than a
single value in these value places then you
| | 04:55 | want to put those in parentheses as well.
| | 04:57 | And we can just stick parentheses
around that, for that purpose for now.
| | 05:00 | So we'll save this, and we'll run it,
and we see we get the 7 because it is
| | 05:05 | equal to five, and if we make it 42,
then it's no longer equal to 5, and now
| | 05:11 | we'll get the 9 value.
| | 05:12 | So it's called the ternary conditional
operator because it's ternary because it
| | 05:16 | has three operands as the condition
and the true and the false operands.
| | 05:21 | And it's called conditional
because it operates on a condition.
| | 05:26 | So ternary conditional operator, you
will hear referred to a lot because people
| | 05:30 | are proud themselves to being able
to remember it and say it, I guess.
| | 05:34 | Conditionals in C are simple and effective.
| | 05:36 | There's one more type of conditional
multiway switch that's covered in the next lesson.
| | 05:41 | So let's go ahead and delete the Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using switch statements| 00:00 | C provides a special multi-way
switch control for branching conditional
| | 00:04 | operations using the switch and case statements.
Let's take a look at how this works.
| | 00:10 | We'll make a working copy of working.c,
and I'm just going to paste it here into
| | 00:15 | the Working project and double-
click on it and open it up there.
| | 00:19 | We're going to put in a switch statement here.
We're going to have to a little other typing.
| | 00:23 | So bear with me for a moment.
Switch statement works like this.
| | 00:27 | If I've a variable like in this, like
in this case I'll make an integer, and
| | 00:31 | I'll call it foo, and we give it value
of 3, then I can have a switch statement
| | 00:35 | like this switch(foo) and give it an empty block.
| | 00:41 | Now depending on the value of foo I can
have it do a number of different things.
| | 00:45 | So I can say case 1 and have it
do puts("one");, and I need a break.
| | 00:52 | I'll explain that in a minute.
| | 00:54 | And if I type case 2, you'll notice that
Eclipse is really nice about formatting
| | 00:59 | this, puts("two");, and a break.
| | 01:03 | Let's just go ahead and copy and
paste it a couple of more times.
| | 01:08 | So if the value is 2, it'll
come down here, it'll put two.
| | 01:11 | If the value is 3, which it is it will
branch to this case 3 and run everything
| | 01:17 | from there to the break.
So if I run this, you see there it prints three.
| | 01:22 | If I were to take out this break,
it would print both three and four.
| | 01:26 | This happens sometimes in Eclipse.
| | 01:28 | You can just click run in the
background, and there you go.
| | 01:31 | So it prints three and four, and you
notice we get a little warning here.
| | 01:34 | It says No break at end of case,
because that's usually a bug.
| | 01:38 | Because usually you want to have a break in
there so that it just does that one conditional.
| | 01:42 | This is what's called a multi-way
conditional or a multi-way switch.
| | 01:47 | One thing you need to be aware of is
these case clauses cannot have a variable.
| | 01:52 | It has to be a constant.
| | 01:53 | So if I had a variable up here, int twovalue
= 2;, and if I'm trying to say case twovalue;
| | 02:02 | then when I try to compile it and run it.
| | 02:04 | I can just press Save, and I'll Run in
here, you'll see I get an error, and the
| | 02:09 | error says case label does not
reduce to an integer constant.
| | 02:13 | So that has to be an integer constant.
| | 02:16 | So I'll put a 2 back there and save
and run it, and it works just fine.
| | 02:20 | So normally what's you end up doing,
especially in C is you end up creating a
| | 02:25 | list of constants and in C a constant
looks like this #define ONE (1) like that, and
| | 02:32 | because this is a preprocessor directive,
and it's not actually compiled, it's
| | 02:37 | run through the preprocessor, and
it's actually a macro, we will learn more
| | 02:41 | about this in the chapter on the
preprocessor, because of that you do not put a
| | 02:45 | semicolon at the end.
The semicolon here would be a syntax error.
| | 02:49 | So let's just create a few of these,
and now in place of these 1, 2, 3, 4, I
| | 02:54 | can say, ONE and TWO.
| | 02:58 | So you want to use constants here if you can.
Just makes it easier to maintain your code.
| | 03:04 | Now you can change all this in one
place rather than having to look for all the
| | 03:07 | places where you need to change it.
| | 03:09 | So I'll save that and run it, and
you see that it works just fine.
| | 03:13 | Now there's also a disadvantage to
using these defines for constants.
| | 03:17 | Unfortunately, in C that's all you've got.
| | 03:19 | In C++ you can actually use real
integer constants, because these aren't
| | 03:25 | processed by the compiler at all.
| | 03:26 | These are processed by the
preprocessor, and they are actually macros.
| | 03:30 | They're subject to side effects and
they don't get into the symbol table.
| | 03:33 | So for a lot of purposes that's all you got.
| | 03:36 | So you use it, but it's
not the best way to do it.
| | 03:39 | For best programming practice, you want to
use integer constants, which only works in C++.
| | 03:43 | So we're going to go ahead and rename
this file, and I'm just going to put pp on
| | 03:47 | the end of it, and that makes it
working.cpp instead of working.c, and now it
| | 03:52 | will compile with the C++
Compiler instead of the C Compiler.
| | 03:55 | I'm going to go ahead and clean the
project to make sure this works on all of
| | 04:00 | the platforms, and I'm going
to bring that up in my editor.
| | 04:03 | Now instead of this #define ONE like
that, I'm going to say const int iOne = 1;
| | 04:11 | like that, and I'm just going to make
four of those, and I'm just going to
| | 04:16 | paste these in down here.
| | 04:18 | Now again, this does not work in C,
it only works in C++, but it does
| | 04:24 | work beautifully in C++.
| | 04:27 | Now these are integer
constants. They're immutable.
| | 04:29 | You can not change them.
They're actually constants.
| | 04:32 | So I can't come down here and say iOne = 42.
| | 04:37 | I'll get a syntax error if I try to
compile and run that, and there it is.
| | 04:43 | See that little error there, it says assignment
of read-only variable 'iOne'. Cannot do that.
| | 04:50 | But for the purposes of the switch statement
for all of these case clauses it does work fine.
| | 04:55 | I am going to go ahead and compile and
run this, and we see that it does exactly
| | 04:58 | what we expect them.
| | 05:00 | I am going to change this value to a
4 and again we're getting this here.
| | 05:04 | You can just switch this Always run in
the background and never see this, but I
| | 05:08 | leave it running, and there we have 4.
| | 05:10 | Now if I change this to another
value like 5, we don't have a case for 5.
| | 05:16 | So if I run that, you'll notice we get nothing.
| | 05:19 | And for that purpose the switch
statement has a default clause.
| | 05:25 | So save that and run it, and now we get default.
| | 05:28 | So any number we put up here, 42 run
that, and it says default, zoom this in a
| | 05:35 | little bit so you can see the whole thing.
So that's how switch works.
| | 05:40 | The multi-way switch control can be very
handy in cases where you need to select
| | 05:44 | a condition from a list of possibilities.
The case statement needs a constant.
| | 05:49 | So you'll need to take special care to use
the proper type of constant for this purpose.
| | 05:53 | Now let's go ahead and bring this back,
and we will delete our Working file and
| | 05:58 | run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using while and do loops| 00:00 | The basic looping
control in C is the while loop.
| | 00:03 | The while loop tests a condition at
the top of the loop, and there's also a
| | 00:07 | version that tests the condition at
the bottom of the loop, and we'll look
| | 00:10 | at both of them here.
| | 00:11 | So let's start by making a working
copy of working.c out of the Chap03 folder
| | 00:15 | I'll copy that and paste it down here in our
Working project and open it up in the editor.
| | 00:22 | So we'll start by defining a variable
for our while loop, I'll just define
| | 00:27 | integer x and give it a value of 5, and
then we'll say while(x > 0) and then our
| | 00:36 | loop here, and we'll printf("x is %d\n", x);,
and then we'll decrement x.
| | 00:47 | So, we'll go ahead and save this and run it,
and we'll see that we have x is 5, 4, 3, 2 and 1.
| | 00:54 | So let's step through it.
| | 00:56 | First we initialize x to be equal to 5,
and we test if x is greater than 0.
| | 01:03 | And it is that first time of course,
and so we print it out, and we get a 5
| | 01:08 | there in our output.
And then we decrement x, and now x is 4.
| | 01:11 | And we get to the end of the block and
so that takes us back up to the testing
| | 01:16 | condition of the loop at the top
of the loop, and it tests again.
| | 01:20 | Now x is 4, so it's still greater than
zero and so we print out the 4 and then
| | 01:24 | the 3, the 2, and when it gets down to 1,
it prints out the 1, and it decrements
| | 01:29 | the x and then the next time it
tests it's no longer greater than the 0.
| | 01:33 | It's also common to just test for x like this
while, because when x hits 0 it becomes false.
| | 01:40 | And so this while like this is testing x
as if it were a Boolean variable and of
| | 01:45 | course in C, there's no Boolean type.
| | 01:48 | There're just integer types
that are tested against 0.
| | 01:52 | So when it's 0 it's false, when it's
not 0 it's true, and so you'll often see
| | 01:56 | it tested like this.
| | 01:58 | In C++ there is a Boolean type, but this
still works, and this is still a common
| | 02:02 | pattern even in C++.
| | 02:04 | So we'll save this, and we'll run it, and
we see that we get exactly the same result.
| | 02:08 | Now there's another version of this loop
called do while, and it looks like this.
| | 02:15 | I'm going to put that in my cut buffer,
and I'm going to say do and open the
| | 02:20 | bracket and close it down here and
say while and put in a semicolon there
| | 02:26 | and get rid of the tab.
| | 02:27 | So do while looks like this, do print
blah, blah, blah while x, and you'll see,
| | 02:34 | because the way we're doing our testing here,
we'll get exactly the same result; 5, 4, 3, 2, 1.
| | 02:40 | The difference is that that we're doing
the test at the end of the loop rather
| | 02:44 | than at beginning of loop.
| | 02:45 | And since I'm doing this decrement at
the end of the loop anyway, we're really
| | 02:49 | getting exactly the same result.
| | 02:50 | Where we get a difference is like this,
I'm going to put it back for a moment
| | 02:55 | the way that it was.
| | 02:56 | I'm just pressing the Undo key on my
keyboard which is Command+Z on a Mac;
| | 03:02 | it would be Ctrl+Z on a PC
and get back to this point.
| | 03:05 | And instead of decrementing the x down here,
I'm going to decrement the x in the loop control.
| | 03:10 | This is also a very common construct,
and it's actually even more common
| | 03:14 | probably to see it done
this way than the other way.
| | 03:16 | We're going to get a different result
though because we're actually decrementing
| | 03:20 | it before we do the printf.
| | 03:22 | And so our results will start at 4 and
go through 1, rather than starting at 5
| | 03:27 | the way that it does.
| | 03:28 | Now because first time through it
starts out at 5, and we decrement it
| | 03:32 | before we even test it.
And so when I run this we get 4, 3, 2, 1.
| | 03:39 | So the decrement operator here being
before the x means that the decrement
| | 03:43 | happens before you test the value,
before you get the result of the expression.
| | 03:47 | If I put the decrement operator after the x
then it'll evaluate x first and then decrement it.
| | 03:53 | And now what we'll get is 4, 3, 2, 1, 0.
| | 03:56 | So I'll save this us, and I'll run
it, and now we get 4, 3, 2, 1, 0.
| | 04:00 | Now if I were to take this and put this
at the end with a do while like that, so
| | 04:08 | now we have do printf, and we have
the condition with the decrement.
| | 04:13 | Let's try it first with the prefix
decrement, and let's see if we can figure out
| | 04:18 | what we're going to get.
| | 04:19 | We'll start out with a 5, and we'll get
all the way down to 1, but we won't get to 0.
| | 04:24 | There we go 5, 4, 3, 2, 1.
| | 04:26 | Now if I take that and make it a
post decrement, now we'll get the 0.
| | 04:31 | And it'll go 5, 4, 3, 2, 1, 0.
So you see you get different results.
| | 04:35 | So the while loop is a fundamental control in C.
| | 04:39 | The while loop tests the condition at
the top of the loop and do while tests the
| | 04:44 | condition at the bottom of the loop.
| | 04:46 | Do while is used less frequently,
but it's still very important to
| | 04:49 | understand both of them.
| | 04:51 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Iterating with the for loop| 00:00 | C provides a very useful iteration
loop control called the for loop.
| | 00:04 | Let's see how this works.
| | 00:06 | I'm going to take a working copy of
working.c and paste it into the Working
| | 00:11 | project and open it up in the editor.
| | 00:14 | First let's just create a simple while
loop, and this is actually an example
| | 00:18 | from a previous movie.
We'll say int x = 5.
| | 00:21 | While we'll printf the value of x,
and then we'll decrement x using
| | 00:28 | the decrement operator.
| | 00:29 | So this initializes x to 5 and then the
first time through the loop, obviously 5
| | 00:34 | is still true as long as
it's nonzero, it's true.
| | 00:37 | Once it hits 0 it becomes false,
and that while loop will end.
| | 00:40 | So it'll print a 5, and it'll decrement,
and then it'll print a 4, and it'll
| | 00:45 | decrement, all the way down to when
this gets to be 0 then it'll stop the loop,
| | 00:49 | and it won't print 0, so
it'll print 5, 4, 3, 2, 1.
| | 00:52 | So save that and run it, and
there we have x is 5, 4, 3, 2, 1.
| | 00:58 | The purpose of the for loop is to be
able to do all of this on one line.
| | 01:02 | So let's go ahead and create this as a for loop.
We'll say for( x = 5; x; --x ),
| | 01:06 | and we'll printf() the value of x,
and let me declare x here with an int.
| | 01:16 | So this for loop is exactly the same
as all of this, and it's really just two
| | 01:21 | lines of code unless you
count this closing brace.
| | 01:25 | So we've reduced the amount of lines of
code, and we've made it actually simpler.
| | 01:29 | Now this might look cryptic at first if
you haven't seen this before, but once
| | 01:32 | you get what this is it's a lot simpler.
| | 01:35 | So I am going to go ahead and delete the
while version, and we'll just take a look at this.
| | 01:40 | The for loop takes three
clauses in the control section.
| | 01:43 | The first clause is the
initializer, and here we say int x = 5.
| | 01:47 | The second clause is really
the while control, while x.
| | 01:51 | And the third clause is do this at
the end of the loop before we start the
| | 01:56 | control again and so here we decrement x.
| | 01:59 | So it's exactly the same code
that we had in the while loop.
| | 02:02 | And so when I save this and run it, you'll see
we get exactly the same result 5, 4, 3, 2, 1.
| | 02:07 | Now it's much more common to do this like this.
| | 02:11 | Say int i = 0 and people tend to
use i because this is an iteration
| | 02:16 | control, while i < 5;
| | 02:20 | and ++i. So if you want to do
something five times, you make a for loop like
| | 02:25 | this, and you say i = 0 while i is less than 5.
| | 02:29 | In C it's tradition to start things at 0,
so testing for while i is less than 5
| | 02:35 | actually ensures it happens exactly 5
times, because when it gets to 5 you've done
| | 02:39 | it five times, and it'll stop.
| | 02:41 | So if we run this it'll say i is 0
through i is 4, and there will still be five
| | 02:46 | lines, i equals 0, 1, 2, 3, 4,
and that makes five lines.
| | 02:50 | So that's a really common way to do this.
| | 02:53 | Also you'll notice that I'm able to
declare and initialize the variable inside
| | 03:00 | the for loop control.
| | 03:01 | This is one of the few places where
this is allowed in C and actually this
| | 03:05 | wasn't allowed in C until C99.
| | 03:08 | So it's only been the last version
of C, of course we are it C11 now.
| | 03:11 | But until recently, C99 was the
latest version and before that this wasn't
| | 03:16 | allowed, and what you had to do is
you had to do something like this, int I
| | 03:20 | and then say for(i=0;).
| | 03:23 | And since it's such a bad form to
declare a variable and not initialize it, it's
| | 03:29 | really prone to errors, if you end up
using that variable for something else.
| | 03:33 | So you would see this int i = 0 and then
nothing in the initializing clause of the for loop.
| | 03:41 | So here we'll see we get exactly the
same result, save it and run it, and we
| | 03:45 | have this sort of odd
looking for loop like this.
| | 03:47 | And so when C99 was ratified, this
became legal, and it made it a whole lot
| | 03:53 | simpler and a whole lot more common.
| | 03:54 | And it has the added benefit that this
particular version of i is really only
| | 04:00 | valid inside of this loop.
| | 04:02 | Outside of this loop if you had an int
i declared outside of it, it would be a
| | 04:07 | separate variable than the
one that's inside the loop.
| | 04:10 | So you don't have your namespace
pollution that you have the other way.
| | 04:13 | Now let's take a look at an example of
how to iterate through an array, because
| | 04:17 | this is another common use of for loops.
Let's create an integer array.
| | 04:21 | We have five elements, and we'll go
ahead and terminate this with a null.
| | 04:25 | We'll put a 0 at the end, so we have
six elements and the last one is the
| | 04:29 | terminator, and it's a 0 and
again that's a common pattern in C.
| | 04:33 | And so we'll declare an integer
pointer here, and we'll initialize it to ia.
| | 04:39 | And remember, with an array the
name of array can be used as a pointer.
| | 04:44 | It's an immutable pointer,
but it's still a pointer.
| | 04:46 | So I can assign it to a
pointer and use that as an iterator.
| | 04:51 | And while what's pointed at it by *ip
is not null so that just looks like that.
| | 04:56 | And then we'll increment ++ip and down
here instead of i we'll say value is, and
| | 05:04 | it's what's pointed out by *ip.
So let's take a look at this real quick.
| | 05:07 | We have an integer pointer, and we're
initializing it to the beginning of the
| | 05:10 | array, the first element in the array.
| | 05:13 | And then we're testing for what's pointed
out by that pointer to see whether it's null.
| | 05:18 | When it gets to null, this test will
become false and the loop will stop.
| | 05:22 | And then we're incrementing the
pointer at the end of the loop.
| | 05:26 | And in the loop we're simply printing
the value of the pointer, so this should
| | 05:29 | come out saying value his 1, 2, 3, 4, 5.
| | 05:32 | So I'm going to save that and run it
and here we have value is 1, 2, 3, 4, 5.
| | 05:39 | So that's actually a pretty common way
to step through an array using an integer
| | 05:45 | pointer or whatever type that
array is that pointer as an iterator.
| | 05:51 | So the for loop is a fundamental
control in C, it's incredibly powerful and
| | 05:55 | useful, and while it may look cryptic
at first, once you to get to know it,
| | 05:59 | you'll find a lot of uses for it.
| | 06:01 | Let's go ahead and delete our Working file and
run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Creating functions| 00:00 | Functions are the basic code structure in C.
| | 00:03 | A function consists of a return type, a
function name, zero or more parameters
| | 00:07 | and a block of code.
All code must be in functions in C.
| | 00:13 | Let's make a working copy of func.c, and
we'll paste this into our Working project.
| | 00:19 | I'm just going to comment this
part out, and we'll use that in a bit.
| | 00:24 | Here we have a function and main which
calls the functional, so we'll go ahead
| | 00:29 | and save this and run it,
and we can see how this works.
| | 00:32 | Now this is a very simple function,
it doesn't take any parameters,
| | 00:35 | it doesn't return a value, and
it's simply called like this.
| | 00:38 | And when you call it, the code inside
the functions block is executed which has
| | 00:42 | this one printf statement.
So the block is where things happen.
| | 00:47 | We could have more things happen in the
block, we could declare a variable, we
| | 00:54 | could initialize a variable, we could do
some math on the variable, and we could
| | 01:00 | print the value of the variable.
| | 01:03 | And many things we can do in there save
it and run it, and you can see i is 25.
| | 01:08 | In fact, if we wanted to, we could
simply return the value of i and in order to
| | 01:14 | do that we need to change the return
type to int and then down here we can print
| | 01:19 | the value, like this.
| | 01:23 | So there we're actually using the
return value directly, we are not even
| | 01:26 | assigning it to anything first.
| | 01:28 | We'll save this and run it, we see we get
value is 25 is so that's from over other.
| | 01:34 | If the return type is void of course,
then it's no longer legal to return anything.
| | 01:40 | And it's no longer legal to take that value.
| | 01:44 | So if I were to try and assign this, say
int x = func() and put the x over here,
| | 01:54 | this is no longer legal.
| | 01:55 | If I save this and run it, it says
void value not ignored as it ought to be,
| | 02:02 | because I've declared it as void.
| | 02:04 | So this type declaration, this actually
dictates the type that the function is used as.
| | 02:11 | So when I try to use this function like
this, the compiler knows that that is a
| | 02:17 | void value, and I can't assign it something.
| | 02:19 | So if I give it an int type, and I give
it a return value, now the type of this
| | 02:25 | function expression is now int, and I
can assign it to an int, and I can use it
| | 02:29 | in the context of an int, and if I
run this, I get the value that I expect.
| | 02:34 | I could also pass parameters to func.
| | 02:36 | In this case let's just pass one
parameter, we'll pass an int, and we'll call it
| | 02:40 | x and instead of adding 25 here
I'll add x, so I'll use it like that.
| | 02:47 | And now when I call it I'll call it
with 50, so we get a different value.
| | 02:51 | So what this does is it
passes this 50 into the function.
| | 02:55 | Now the way that it does that is by
declaring a new temporary variable, and
| | 03:00 | copying this value into that variable.
| | 03:03 | So it's not actually using the 50 directly,
it's actually copying it into the function.
| | 03:09 | This called call by value and all
functions in C are called by value.
| | 03:14 | So if I save that and run it, now the
value is 50, because it's getting added to
| | 03:18 | the i which was zero.
| | 03:20 | In fact, if I were to have int y =
50 and then pass the y instead, same thing
| | 03:28 | happens, it's making a copy,
it's not directly using y.
| | 03:32 | So if I run that, that's what happens.
| | 03:35 | Now instead if I wanted to actually
change the value of x here, x = 100, and if
| | 03:44 | we come out here and also print the
value of y, you'll see that y doesn't get
| | 03:50 | changed, and that's because this is
passing the value, it's not actually passing
| | 03:55 | a reference to the variable.
So the function has no way of affecting this y.
| | 03:59 | So if run this you'll see y is still 50.
| | 04:02 | If I want to be able to affect y, then
what I have to do is I have to pass a pointer.
| | 04:08 | So I can pass y like this, that's the
address of operator if you'll remember,
| | 04:14 | and then this one has become a pointer.
| | 04:16 | Then I have to use it as a
pointer in all of these places.
| | 04:21 | So now my parameter is a pointer and what
I'm passing it is the address of a variable.
| | 04:28 | So now I'm actually able to affect this
variable, and when I assign a 100 to it
| | 04:32 | I'm assigning it through the pointer,
so I'm dereferencing the pointer and so
| | 04:35 | that has the address of his variable
and so it's actually going to affect this
| | 04:39 | variable and then y will be a 100.
| | 04:41 | So we'll save this and run it, and you
see that the variable actually affect our
| | 04:46 | variable and so that's called pass by
reference as opposed to pass by value.
| | 04:50 | C is always pass by value, and I'm still
passing a value, it's just the value is now a pointer.
| | 04:56 | And so that's how I'm able to affect
variables outside the function, and that's
| | 05:00 | how I'm able to implement call by
reference instead of call by value.
| | 05:04 | So let's put this back to how we had
it before, which was call by value, save
| | 05:08 | that and run it and see that it's
working the way that we expected.
| | 05:12 | Now if were to move this function to
after main, if i try to compile it and run
| | 05:18 | it, I get a warning here,
implicit declaration of func.
| | 05:22 | And so the compiler was able to discern
it, but it's really wrong, and you don't
| | 05:26 | want to do it this way.
| | 05:28 | In this case the compiler was able to
tolerate it, but many compilers will
| | 05:33 | simply give you an error.
| | 05:34 | In order to properly use this function
when it's used before its definition is
| | 05:39 | to have a declaration.
| | 05:41 | So I take the function signature and the
function signature is the return value,
| | 05:46 | the name and any parameters just their types.
| | 05:50 | The actual variable name is not
part of the function signature.
| | 05:54 | Now it's common to include the name,
because it often gives a hint of how it's
| | 05:59 | used and so we'll leave that in there.
| | 06:01 | Now you'll see this warning will go away
when we save it and run it, so now that
| | 06:05 | warning goes away, because we've told
the compiler exactly what that function
| | 06:08 | looks like, and that it will be defined later.
| | 06:11 | What's really common is that the
function itself is actually in a separate
| | 06:16 | translation unit, it's in a separate
source file, and it's linked in later.
| | 06:21 | And what's even more common is instead
of having this function signature here to
| | 06:25 | have it in a header file.
| | 06:28 | So I am going to uncomment this, and I
am going to take this func.h, and I'm
| | 06:33 | going to copy it and paste it into our
Working project, and we'll open it up, we
| | 06:37 | see there we have a declaration of the
function, that's actually not how we have
| | 06:41 | it defined it right now.
| | 06:42 | So I'm going to copy this and paste it
in there, and there is our declaration of
| | 06:47 | the function signature.
| | 06:48 | And now that's included in this
header file, and this will compile and run
| | 06:53 | without error or warning.
| | 06:54 | So that's the common way to do this,
whatever functions you are using in a
| | 06:58 | particular source file to have their
function signatures in a header file.
| | 07:02 | And what that allows me to do is if I
have a set of functions, I can have all of
| | 07:07 | those in one source file, and I can have
all of their function signatures in the
| | 07:11 | header file, and I can
compile that as a separate unit.
| | 07:14 | And then when I want to use that
and link to it, all of those function
| | 07:19 | signatures are in the header file, and
I can simply include that header file
| | 07:24 | in my main program, and link to the code and
everything will work the way that I want it to.
| | 07:30 | So this is really the common way to do
this, this is how libraries are created.
| | 07:34 | In fact, this is why we include <stdio.h>
at the beginning of all our programs.
| | 07:40 | Because functions like printf() and puts()
that we use a lot are defined in <stdio.h>.
| | 07:46 | And then the actual code is linked
in with our program as we build it.
| | 07:50 | So that's how our standard
libraries work, and that's really how all
| | 07:53 | libraries work in C.
So the function is the basic unit of code in C.
| | 07:58 | Everything starts from the main function
and all code must be in function blocks.
| | 08:03 | Understanding functions is a
fundamental skill for C and C++ programming.
| | 08:06 | Now let's delete our working files and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Branching with goto, break, and continue| 00:00 | C provides three basic branching controls,
goto, break, and continue.
| | 00:06 | These controls should be used with care.
| | 00:08 | Under many circumstances they can be
very difficult to debug, and they are use
| | 00:13 | often indicates flawed logic.
| | 00:15 | On the other hand, especially with
break and continue, there are circumstances
| | 00:19 | when they are entirely appropriate and expected.
Let's start with goto.
| | 00:24 | Let's make a working copy of goto.c,
and we'll paste it in the Working project
| | 00:29 | and double-click on it to open it up.
| | 00:32 | Here you see we have a label which
looks like that, it's a token with a colon
| | 00:37 | after it, and it's the only thing on a line
it's not a statement, it's simply a label.
| | 00:42 | And we have a goto
statement which targets that label.
| | 00:46 | It says goto and then the name of the
label, which in this case is target.
| | 00:50 | So what will happen here is the goto statement
is basically an unconditional branch.
| | 00:56 | When the execution encounters the goto
statement, it'll simply skip to the target.
| | 01:02 | So this printf will never be executed,
we'll get Before the goto, and we'll get
| | 01:07 | After the target but we
will not get After the goto.
| | 01:09 | So let's go ahead and compile and
run this, and you see Before the goto
| | 01:13 | and After the target. So that's simple.
| | 01:16 | Like I said, you're not going to need
it very often, you rarely actually going
| | 01:20 | to need it, when you do need it, you're
going to think twice, three times, and
| | 01:24 | if you find that your logic is
actually sound, and this goto is the best way
| | 01:29 | to do it, then you'll comment it really good,
and you'll use it, and that's how it works.
| | 01:34 | The break statement is used in loops.
| | 01:36 | It will branch to the end of the
current loop or switch control, and execution
| | 01:41 | will continue after the loop,
it will not continue the loop.
| | 01:45 | So let's take a look at this.
| | 01:47 | We'll go ahead and delete these lines,
and we'll create a simple for loop.
| | 01:51 | So there is our simple for loop, and it
will print ten lines, and we'll count 0 to 9.
| | 01:56 | So we'll go ahead and save that and run
it, and you see there are our ten lines,
| | 02:01 | I'm using my little scroll wheel
here, and that's what they look like.
| | 02:05 | Now if we want to we could break out of
this, and we could say if(i == 5) break;
| | 02:12 | and so now it will only print 1 through 4,
and when it sees 5 it'll actually end
| | 02:16 | the loop prematurely.
| | 02:17 | So we'll save this and run it, and there we are.
0, 1, 2, 3, 4, and when it gets to 5, it breaks.
| | 02:25 | Break is most commonly used in switch
controls, and you'll see a good example of
| | 02:30 | that in the lesson on switch in this chapter.
| | 02:32 | On the other hand if we use continue,
instead of break, what continue does is it
| | 02:38 | goes back to the top of the control.
| | 02:41 | It will skip everything after the
continue in the block and go back to the
| | 02:45 | top of the control.
| | 02:47 | So in this case what it'll do is
it'll print 0, 1, 2, 3, 4, 6, 7, 8, 9.
| | 02:52 | Because when it sees 5, it'll skip
everything after the continue which is this
| | 02:57 | printf, the body of the loop, and
it'll go ahead and continue with the loop.
| | 03:01 | So we'll save that and run it, and there
you see we have it 1, 2, 3, 4, 6, 7, 8, 9.
| | 03:07 | So it's just skipping that one
iteration, but it continues with the loop.
| | 03:12 | So these branching controls are an
important part of the C language, but they
| | 03:16 | should really, rarely be used.
| | 03:18 | Most of the time they're unnecessary
and even problematic, but when you need
| | 03:22 | them it's important to know how to use them.
| | 03:25 | So let's delete the Working file and run
Clean and get set up for the next lesson.
| | Collapse this transcript |
|
|
4. The C PreprocessorAbout the C preprocessor| 00:00 | The C Preprocessor provides a number
of essential capabilities for both the
| | 00:04 | C and C++ languages.
Let's take a quick look at what it does.
| | 00:10 | In order for your source code to become an
executable program it first needs to be compiled.
| | 00:15 | But what we need to realize is that
this Compiler is really several things in
| | 00:21 | one package, preprocessor, compiler,
optimizer and linker and often more.
| | 00:27 | Each of these steps is separate and
distinct even though they're often
| | 00:30 | invoked with one command.
| | 00:31 | For now the step we're
interested in is the preprocessor.
| | 00:35 | One of the more common uses for
the preprocessor is file inclusion.
| | 00:41 | When you use the #include directive
your source file be treated as if the
| | 00:45 | entire contents of the file you name here
were included in place of the include directive.
| | 00:50 | Then this combine file called a
translation unit is passed to the compiler.
| | 00:57 | A preprocessor macro works
like a really smart alias.
| | 01:00 | For example, after this declaration
and use of the word CONSTANT in all caps
| | 01:06 | will be replaced by the digit 1.
| | 01:08 | No math is performed, this is really just
a string substitution in the source file.
| | 01:13 | In this second example we
have a macro with parameters.
| | 01:17 | Those parameters maybe used in the replacement.
| | 01:19 | This construct is common in C, less so in C++
where templates are often used instead.
| | 01:27 | Conditional processing allows you to
compile parts of your code only if certain
| | 01:30 | conditions are true.
| | 01:32 | In this common example, the contents of
a header file are only processed once.
| | 01:37 | This technique is called an include guard.
| | 01:39 | Keep in mind that this step happens
before compilation, so you may only use
| | 01:44 | constants and preprocessor
macros for your conditions.
| | 01:49 | Pragmas maybe used to define
implementation specific behaviors for the compiler.
| | 01:54 | Most common uses of pragmas relate to supporting
certain compilers and computing architectures.
| | 02:00 | Be careful using pragmas,
they are typically not portable.
| | 02:04 | The C preprocessor is an essential
part of the compiler toolchain and
| | 02:08 | understanding how it works and what it can be used
for is an essential part of learning C and C++.
| | Collapse this transcript |
| Defining constants| 00:00 | One common use for the
preprocessor is to define constants.
| | 00:03 | In fact, the preprocessor cannot
define constants or any other C language
| | 00:08 | object, but it does have a feature
that's commonly used for this purpose.
| | 00:11 | Let's start by make a working copy of
working.c out of our Chap04 folder in
| | 00:16 | the exercise files.
| | 00:17 | I'll just Paste this into our Working
Project and open it up in the editor.
| | 00:22 | Now if I come down here and use the
define directive #define, and I'll give it a
| | 00:29 | symbol ONE and a value of 1.
| | 00:32 | Now what this does is during the
preprocessor stage before anything gets passed
| | 00:36 | the Compiler, every time it sees the
text string with the capital letters ONE it
| | 00:43 | replaces that was the digit 1.
| | 00:46 | And that's literally what it does.
| | 00:47 | So this is not actually a constant,
there is no symbol in the symbol table, it
| | 00:51 | doesn't have a type, it is
really just a string substitution.
| | 00:56 | You'll also notice that there is
no semicolon at the end of the line.
| | 01:00 | This is the Preprocessor, this is not
C, it's actually not the C language.
| | 01:04 | It's a separate language that's used
by the C Preprocessor and the same C
| | 01:08 | preprocessor could be used with
any language and actually often is.
| | 01:12 | In fact, what this is is a very, very
simple version of a preprocessor macro,
| | 01:16 | and we'll talk about macros in
more detail later in this chapter.
| | 01:19 | But really what this is is a
very, very simple form of a macro.
| | 01:24 | So if I come down here in printf, and I
say, The constant is, and I'll put in a
| | 01:32 | %d, and we'll put ONE over here.
| | 01:35 | What will happen when the preprocessor
runs through the file, it'll actually
| | 01:39 | take this string, letters O-N-E, and
it'll replace them with a literal number 1,
| | 01:46 | which is a literal token
it's not actually a constant.
| | 01:50 | So if I do this and go ahead and
Compile and Run it you'll see that we'll
| | 01:55 | get, The constant is 1.
| | 01:56 | And now if I come up here, and I change
this and make it a string, and it says
| | 02:02 | One like that and Save that and Run it,
we'll get a syntax error because you
| | 02:08 | notice the warning here, format expects
an argument of type int but got a type
| | 02:12 | character pointer, and down here we
get the address of that character pointer
| | 02:16 | because it's really trying to do what it can.
| | 02:19 | So this is not typed, this is
really just a string substitution.
| | 02:23 | On the other hand, if we change this to
s in the printf and save it and Run it,
| | 02:29 | it works exactly as we expect.
| | 02:32 | Because this is a simple text
substitution sometimes there can be unintended
| | 02:37 | consequences and side effects, and so
one thing that's done to mitigate that is
| | 02:42 | it's very common to take all of your
macro constant things like this and enclose
| | 02:47 | them in parentheses.
| | 02:48 | Again, in this case it'll work just
fine, and there are some cases where the
| | 02:54 | macro substitution can create ambiguous
syntax, and this tends to mitigate that problem.
| | 03:01 | So the problems with this approach,
it has no type, you can't use it with a
| | 03:06 | pointer, it has no symbol in the Symbol
table, it's really not a constant it's
| | 03:10 | simply a text substitution.
| | 03:12 | Alternatives are instead of using a
define, in many cases you can actually use
| | 03:18 | a constant variable.
| | 03:19 | You can say something like const int
iOne = and give it a 1, and now that's an
| | 03:26 | actual variable, and this
symbol ONE no longer exist.
| | 03:29 | So if I say, iOne and make this an int,
now what we've is an actual constant,
| | 03:36 | and it's actually part of the
language, and it's in the Symbol Table.
| | 03:39 | If I go ahead and I Run it I can run it.
I can create a pointer and take its address.
| | 03:48 | And then I can do this,
and that works, Save and Run.
| | 03:52 | We're getting the result that we expect.
| | 03:54 | We have a little warning here that the
initialization discards the constant qualifier.
| | 03:59 | So this should probably be a
constant integer pointer, of course, that
| | 04:04 | constant go before or after.
| | 04:06 | I Save and Run, and we
see that warning goes away.
| | 04:10 | So this is actually strongly typed.
| | 04:12 | As you saw that we got a warning
where the type was just a little bit off.
| | 04:16 | Just like any variable in
C it's in allocated memory.
| | 04:19 | We can take a pointer to it;
| | 04:20 | it's in the Symbol table
so debugging becomes easier.
| | 04:24 | It cannot be used in C where a
literal constant is required as with the
| | 04:29 | switch and case statement.
But in C++ you actually can do that.
| | 04:33 | So Preprocessor macros are
often used to define constants in C.
| | 04:37 | It's important to realize that in fact
they are not constants, rather they are
| | 04:42 | simple text replacements.
| | 04:43 | So often better to use variables
declared with the const keyword where
| | 04:47 | that's actually possible.
| | 04:48 | So now let's delete the Working file and
run Clean to get ready for the next lesson.
| | Collapse this transcript |
| Including files| 00:00 | You'll typically have a list of #include
directives at the top of each source file.
| | 00:04 | This is probably the most common or at
least the most visible use of the preprocessor.
| | 00:08 | Let's start with a working copy of our
working.c, copy and paste that into the
| | 00:14 | Working folder, and double-
click on it to open it up here.
| | 00:18 | You'll notice at the top there, I
have this #include<stdio.h>, the #include
| | 00:25 | directive, that's the pound sign, and
word include is used to include a header
| | 00:30 | file in a source file.
| | 00:31 | The preprocessor replaces the #
include directive with the contents of the
| | 00:35 | included header file, then takes that
combined file and passes that onto the compiler.
| | 00:40 | Multiple include directives are
allowed and are in fact common.
| | 00:44 | All the #include directives are
processed, including those nested within other
| | 00:48 | included files and they are all
combined into one piece, and that one piece is
| | 00:52 | often called a translation unit.
| | 00:55 | There are in fact two basic
forms of the #include directive.
| | 00:59 | One form using the angle brackets, as
we see here is used at the top of each
| | 01:04 | of our working files.
It says #include<stdio.h>.
| | 01:08 | This form with the angle brackets
instructs the preprocessor to search for
| | 01:12 | the included file using a set of
predefined locations that are defined as
| | 01:16 | part of the implementation.
| | 01:18 | This form is typically used for
system-level headers that are common to
| | 01:22 | different projects in source files.
The other form, using double-quote marks.
| | 01:26 | I'm going to go ahead and type one here.
| | 01:28 | This form is commonly used for
header files that are specific to a given
| | 01:32 | project or a source file.
| | 01:33 | This does not search for files
in the system header locations.
| | 01:37 | So, in order to use this, I have to
take this preproc.h, and I'm going to copy
| | 01:42 | and paste that into our Working project.
| | 01:44 | Now, you notice that the little
question mark goes away, and we can actually
| | 01:48 | save this and run it.
| | 01:50 | If we look in that header file, we'll
see it defines our little constants here.
| | 01:55 | So I can take this one, and I am just
going to copy that symbol and come over
| | 02:00 | here in Working, and I am going to say
printf("the constant is %d, put in a new
| | 02:09 | line, because that's always a
friendly thing to do, and paste in my symbol.
| | 02:12 | That symbol is defined in that include
file, and so when I save this, and run
| | 02:19 | it, it finds the constant just fine
because that is defined in this include
| | 02:23 | file, and this is run as if that entire
include file was just typed right there.
| | 02:28 | The #include directive is an
essential part of C and C++ programming.
| | 02:32 | While it's certainly not required,
virtually every source file we use at
| | 02:37 | least one #include directive and often more.
| | 02:39 | Even if it's just for your
standard library headers.
| | 02:41 | Now, let's delete the working files and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Exploring conditional compilation| 00:00 | The C preprocessor provides a number of
directives for conditional compilation.
| | 00:05 | There you see a list of them.
| | 00:07 | #if, #ifdef, #ifndef--which is the
negative of #ifdef--#else, #elif, and #endif.
| | 00:15 | There's also this other version of #
ifdef called #if defined which some
| | 00:19 | people prefer to use.
Let's take a look at how this works.
| | 00:23 | Let me take a copy of conditional.c and
conditional.h, and copy and paste those
| | 00:29 | into the Working project,
and open them up in the editor.
| | 00:32 | Here is conditional.h, and you'll
notice in here that it defines the number 2,
| | 00:37 | and it has an #ifdef for a symbol
called FOO which we know is not defined, and
| | 00:42 | then it redefines the number to be
47 inside of the #ifdef and #endif.
| | 00:49 | You'll notice over here that we
don't have that symbol defined.
| | 00:52 | So, when I compile and run this, I get
a number 2 which is the number that's
| | 00:57 | outside of the #ifdef.
| | 00:58 | Now, if I go ahead in here, and I define
the symbol foo, #define FOO, you notice
| | 01:06 | it really doesn't change anything.
| | 01:07 | I will compile and run this,
and we still get the number 2.
| | 01:10 | The reason for that is that my symbol
is defined after the include, and you
| | 01:14 | remember that the include, all it does
is it includes everything right there in
| | 01:18 | line, and I've got that symbol defined
afterwards, and so at this point, that
| | 01:21 | symbol is not actually defined.
| | 01:23 | So, if I move my include, and put it
down here after the #define, and I run
| | 01:31 | this, Compile and Run, we get the number 47.
| | 01:34 | You notice we have a little warning
symbol there on the conditional.h, and
| | 01:38 | that's because what we
have is a number redefined.
| | 01:42 | So, of course, it's actually
legal, it's really just a warning.
| | 01:45 | But there is a better way to do this.
| | 01:48 | We can use #else, and I can take this #
define NUMBER 2, and I can put it down
| | 01:54 | here, and in between, I can put an #else.
| | 01:56 | Now, what happens is when I compile and
run this, the warning goes away because
| | 02:05 | only one of these definitions is
going to be in effect at a time, and if I
| | 02:11 | remove this definition, comment that out,
and Save and Run, now the number is 2
| | 02:16 | again, exactly how we expect.
| | 02:19 | You notice that Eclipse does a nice job
here of graying out the parts that are
| | 02:22 | not in effect and leaving the
parts that are in effect ungrayed.
| | 02:26 | Instead of #ifdef, you can also use
#if defined, and put this symbol in
| | 02:32 | parentheses, and it's just
another syntax for the same thing.
| | 02:36 | If we save and run this, we
get exactly the same result.
| | 02:40 | So, the C preprocessor provides
conditional compilation directives.
| | 02:43 | They're commonly used for separate
versions of code, for debug, or for
| | 02:48 | supporting different target environments.
| | 02:49 | Let's go ahead and delete our working copies
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Defining macros| 00:00 | The C preprocessor provides a powerful
and flexible macro system, let's take a
| | 00:05 | look at how this works.
| | 00:07 | Take a working copy of working.c and paste it
into our Working project and open it up here.
| | 00:14 | Now we've seen the macros that look like this.
| | 00:19 | And that's very common and its use to
provide something that looks like a constant.
| | 00:24 | What we're going to this time is
something that is a little bit more
| | 00:28 | complicated, we're going to define
macro we will just call MACRO1, and this
| | 00:32 | macro is going to have parameters.
And so we'll just call those parameters a and b.
| | 00:37 | And the result that it'll simply a * b.
| | 00:41 | And so if I come down here into the
main part of the program, and I define an
| | 00:46 | integer so I will call an integer this,
and let's say that its 5, and I'll call
| | 00:52 | an integer that and give it a 7.
| | 00:54 | And then in my printf I'll just say
this is %d that is %d and result is %d.
| | 01:06 | And let's put this on the next line for
clarity here, and I'll say this, and that
| | 01:10 | and MACRO1 and pass it this, and that.
| | 01:17 | So, remember in C that white space is
mostly non-consequential so putting this
| | 01:22 | in on another line doesn't change how it works.
| | 01:25 | Just doing that so that it's
easier for us to see on the screen here.
| | 01:29 | And so I'll save this, and I'll run it
and what do we except to have happened,
| | 01:33 | we'll get a 5, and we'll get a 7, and
then we'll get 7 times 5 which is 35.
| | 01:38 | And there we go, so we got this,
we got that, and we got 35.
| | 01:42 | And so you can obviously do things that
are much more complicated with a macro
| | 01:46 | like this, it's not
uncommon to do something like this.
| | 01:49 | If a is greater than b, then result would
be an a otherwise the result will be a b.
| | 01:55 | And so it'll simply give us the greater
of them and so now the result will be a
| | 02:00 | 7, we will compile and run that, and we get a 7.
| | 02:03 | And if we change this around to a
less than b then our result will be a 5.
| | 02:09 | So, as we use these macros again it's
important to think about the possibilities
| | 02:14 | of side effects, so its really
common to go ahead and quite everything in
| | 02:18 | parentheses() especially when you got
operators here now you are going to be
| | 02:22 | dealing with Operator Precedence.
| | 02:23 | You might be doing something like this
times that in the beginning macro, and
| | 02:28 | then you have to really think, well
what is the result of that going to be?
| | 02:32 | I don't know what's the precedence is it
going to evaluate the asterisk first is
| | 02:37 | it going to evaluate the less than
sign first, I'd have to look upon my handy
| | 02:41 | dandy operator precedence chart
to predict it, and I'd just run it.
| | 02:44 | But if I'd up just put these in
parentheses put the a in parentheses and the b
| | 02:48 | in parentheses and the next a in
parentheses, and now the next b in parentheses.
| | 02:54 | And then I'll often put the entire
thing in parentheses which I've done here,
| | 02:58 | you can see I've got see
this parentheses on the outside.
| | 03:01 | And now when I run it I know that you
have got a less than so I'll get that,
| | 03:06 | I'll get the 7, and if I run that I
get a 7, and if change this to a greater
| | 03:11 | than I'll get a 35, save and run it.
| | 03:14 | So it is important to think about the
side effects when you're using macros you
| | 03:18 | need to really think it through, The side
effects can be very-unexpected and dangerous.
| | 03:23 | So while the use of function like
MACROS is common in C and in fact the
| | 03:27 | preprocessor was even designed to do this.
| | 03:30 | For many uses C++
templates are a superior solution.
| | 03:34 | So if C++ is an available option, templates are
generally recommended over parameterized MACROS.
| | 03:40 | Now let's delete the working files and run
Clean to get to set up for the next lesson.
| | Collapse this transcript |
| Macro caveats| 00:00 | A common problem with preprocessor macros is
the possibility of unintended results.
| | 00:05 | A common cause of problems is
parameters being evaluated more than once.
| | 00:10 | Let's take a look at how this can happen.
| | 00:12 | Make a working copy of working.c and paste it
here into our Working Project and open it up.
| | 00:18 | And now we're going to do little bit of coding.
| | 00:20 | We'll start by creating a
function called increment().
| | 00:23 | All this function does is increment a value.
| | 00:27 | So we'll start by defining a static int,
and then we're going to increment it,
| | 00:32 | and we'll increment it by 5 and return it.
| | 00:36 | So every time this function is
called it will return 5 more than the last
| | 00:40 | time, starting with 47.
| | 00:41 | I'm going to go ahead and put in a print
statement so that we can see what's happening.
| | 00:47 | So printf(increment returns %d,
semicolon there, and so now we have a print
| | 00:55 | statement every time increment gets
called, and it will printout, and it's
| | 00:59 | getting called and what it's returning.
| | 01:00 | Now let's define a macro and our macro
is going to be a very common one, called
| | 01:05 | MAX, and it's simply returns the
maximum value between two parameters.
| | 01:09 | So we've got a and b, and it returns, a > b,
it'll return a and otherwise it'll return b.
| | 01:16 | And I'm going to go ahead and put these
in parenthesis, because that's always a
| | 01:20 | good idea to do, a in parenthesis,
and b in parenthesis. There we go.
| | 01:27 | So that's our macro, and now we'll come
down here, and we'll use it, and this is
| | 01:31 | where the fun begins. int x = 50;
so we've got a number there.
| | 01:37 | I'm going to change this printf out,
we'll say, max of %d and %d is %d. So the
| | 01:47 | parameters are, I'll go ahead and put
this on a separate line just for clarity,
| | 01:51 | x and increment, an increment() call, and then
we're going to say, MAX(x and the increment() call.
| | 02:02 | It seems to think I've got
a typo here someplace.
| | 02:04 | Let's see what happens when I copy and paste it,
because I want two of them in here anyway. Ah!
| | 02:09 | That's what's it is I'm missing the Comma.
| | 02:12 | Stare at these things long enough,
and it usually jumps out at you.
| | 02:15 | Okay, so I'm going to save this and
run it, and we're going to get some
| | 02:18 | interesting results here.
| | 02:20 | So increment is getting called twice
here, before the first result, and that's
| | 02:25 | what we expect because we have it
once there, and we have it once there.
| | 02:29 | Now function parameters actually
evaluate right to left, so this one is actually
| | 02:33 | getting called before this one.
| | 02:35 | So the first time through it returns a
47 which is what we expect and so that
| | 02:41 | would be this first
evaluation, it would be this b here.
| | 02:45 | And because 50 is greater than 47 that
doesn't get called again, instead it returns 50.
| | 02:51 | And the 50 actually gets evaluated
twice, but that doesn't have any impact.
| | 02:56 | And so then it calls increment() again,
and it says here, increment returns 52,
| | 03:01 | and that's the one that's
getting displayed here in the printf.
| | 03:05 | So the max of 50 and 52 is 50, which is
not exactly correct, but it's the result
| | 03:11 | we get, because the first time
through that evaluation of a and b here was
| | 03:16 | actually 47, it wasn't 52.
| | 03:19 | And 47 is less than 50 and so the max of
50 and 47 is 50, but it's displaying 52
| | 03:25 | because it's evaluating that a second time.
| | 03:28 | So if that's not confusing enough, let's
look what happens the next time through.
| | 03:32 | Now the next time through, again it
evaluates MAX first, and it compares x to 57.
| | 03:42 | And it says oh 57 is greater than 50
and so it returns 62 because it goes and
| | 03:49 | evaluates increment() again.
| | 03:52 | So the first evaluation is here and the
second evaluation is there because this
| | 03:56 | condition was satisfied and b is the
one that's being called, and so increment
| | 04:01 | gets called twice, and it returns a 62.
| | 04:04 | And yet it gets evaluated even a third
time for the printf and so the printf
| | 04:11 | comes out, and it says max of 50 and
67 is 62, which is completely wacky.
| | 04:19 | So you can see that we have this
unintended consequence, because increment() is
| | 04:23 | getting evaluated all over the place
and its results are getting all mixed up.
| | 04:28 | If we actually trace through we can see
what's happening and why, but it can be
| | 04:32 | really confusing and especially if your
macros are anymore involved than this.
| | 04:37 | So function like macros are a powerful
tool, but like many powerful tools you
| | 04:41 | need to be conscious of how they work.
| | 04:43 | If you're using Standard C, and you
don't have C++ templates or Inline functions
| | 04:48 | available, then just proceed with care,
you'll need to be conscious of how your
| | 04:52 | macros are evaluated.
| | 04:53 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with line continuation using the backslash| 00:00 | Line continuation is a
convenient function of the Preprocessor.
| | 00:05 | This is something you may not need
very often, but when you do need it, it's
| | 00:08 | good to know it's there.
| | 00:09 | Let's start with a working copy of
working.cout of our Chap04 folder here, and
| | 00:14 | paste it into our Working
Project and open it up in the editor.
| | 00:18 | So the interesting thing about
this is that it works everywhere.
| | 00:21 | It doesn't work just in Preprocessor directives.
| | 00:24 | If I put in a Backslash here right in
the middle of the string and press the
| | 00:28 | Enter key, well of course, Eclipse is
going to try and give me what it thinks I
| | 00:33 | want as opposed to what I actually want.
| | 00:35 | So I need to come and
clean this up a little bit.
| | 00:37 | But you see that Backslash followed by
the new line, and I can't select the new
| | 00:41 | line there, but that Backslash followed by
the new line is the line continuation sequence.
| | 00:48 | And when I run this I'm going to go
ahead and Save it and Run it, and I'm
| | 00:53 | just going to hit this Run in the
Background button, and you'll see that it
| | 00:56 | says Hello, World! all in one line.
| | 00:59 | In fact, if I were to move this over
there in the middle of the word Hello and
| | 01:06 | save it and run it, it
still puts it all in one line.
| | 01:09 | And that's because this is what's
called the line continuation sequence.
| | 01:12 | So Backslash followed by new line
will be completely folded out and ignored
| | 01:18 | by the Preprocessor.
The Preprocessor will reassemble it.
| | 01:22 | The real purpose for this is when
you're defining Macros if your Macros are
| | 01:27 | very long, and you want to preprint
for your own purposes, a macro needs to
| | 01:32 | actually be all on one line.
This is not a valid macro.
| | 01:37 | The macro ends at the end of the line,
there's no other indication of where a
| | 01:42 | macro ends, that's just a quirk of
the Preprocessor and how it works.
| | 01:46 | The way that you get around this
is with this line continuation.
| | 01:49 | So I'm going to go ahead and I'm going
to define a fairly complicated MACRO here.
| | 01:53 | This is a common SWAP function
that you'll see now and then.
| | 01:57 | And it actually uses a do loop and the
reason that it uses this do loop is so
| | 02:02 | that it can have a block.
| | 02:03 | And so it doesn't actually do any
looping, it just does that, and we use the
| | 02:08 | line continuation character to put it
all in one line so that the preprocessor
| | 02:13 | knows what's going on.
| | 02:14 | And I can put my lines
inside of here, I can say, a ^= b;
| | 02:21 | and then another line continuation
character out there, and I'm just going to
| | 02:25 | copy this line three times because
this is the way this macro works.
| | 02:30 | And so now I've got this MACRO defined
with these line continuation characters,
| | 02:34 | and it's still fairly readable.
| | 02:36 | And so I can come in here,
and I can say, int this = 7;
| | 02:43 | and int that = 9;, and I can printf("
this is %d, and that is %d with this, and
| | 02:54 | that, and I'm going to make two copies
of that and in between them I'm going
| | 02:58 | to run the SWAP Macro.
| | 02:59 | Now when I save this and run it we'll
see this is 7, and that is 9, and this
| | 03:04 | is 9, and that is 7.
| | 03:06 | So it's a common little trick, it
only works with integers, but it's made
| | 03:11 | readable by using the
line continuation sequence.
| | 03:15 | So the preprocessor provides a
useful line continuation feature using the
| | 03:19 | Backslash new line combination.
| | 03:21 | This is really convenient for
making complex Macros more readable.
| | 03:25 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Including files only once| 00:00 | When a header file is included by
other header files, there is a possibility
| | 00:04 | that it can be included more than
once, and this can create errors.
| | 00:08 | Let's take a look at a simple example.
| | 00:10 | I am going to go ahead and copy
includeA and includeB and working.c.
| | 00:18 | Make a copy of those and paste them
into our Working project.
| | 00:22 | And I'm just going to go ahead
and open up all three of them.
| | 00:28 | And in includeB, I'm going to go
ahead and I'm going to type #include
| | 00:35 | "includeA.h" and includeA
does not include includeB.
| | 00:41 | And then if I'm going to come in here
into working.c, and I'm going to include
| | 00:45 | both of them, #include "
includeA.h" and "includeB.h".
| | 00:54 | I'll save that, and when I go ahead and
build it, you'll notice that I get errors.
| | 01:02 | And here in includeA, let's see it's
got a little x there, I'll select that,
| | 01:06 | and I'll hover my mouse, and it says -
originally defined here - redefinition
| | 01:10 | of 'struct structA'.
| | 01:12 | And the reason for that is
that I've included includeA here.
| | 01:16 | And so that structA is getting defined,
and then I've included includeA here in
| | 01:23 | includeB which also gets included here.
So includeA is getting included twice.
| | 01:29 | So the typical solution for this is what's
called an include guard, and it looks like this.
| | 01:34 | Pound if defined, #ifdef. And I'll
use an underscore here, and I'll say
| | 01:40 | INCLUDE_A then I'll go ahead and
define INCLUDE_A, actually this should be an
| | 01:47 | ifndef, if not defined, I'm going to say
INCLUDE_A and then down here at end I'm
| | 01:54 | going to put #endif, and I'll
put in a comment. All right?
| | 01:59 | And now, the first time through
INCLUDE_A is not defined and so all of this
| | 02:06 | will get evaluated, and it'll define
INCLUDE_A so that the next time through
| | 02:11 | that doesn't happen.
| | 02:12 | So now when I compile and run,
you see we don't have any errors.
| | 02:17 | Of course, we can do the same thing in
includeB which would be nice to do, and
| | 02:24 | we'll call this INCLUDE_B instead, but this
is not really where we're having the problem.
| | 02:31 | And we save that and run it,
and it all works just fine.
| | 02:35 | So that's called include guard, and
you will see this pattern very often in
| | 02:39 | header files actually you'll see it in a
lot of the header files in this course.
| | 02:43 | And if you were to look at your
standard header files which I really suggest
| | 02:47 | that you do, they're often
very educational and very cryptic.
| | 02:50 | You'll see this pattern a lot in them.
| | 02:52 | Many modern compilers have a
nonstandard feature called #pragma once, and if I
| | 02:59 | take this include guard out of here and
instead at the top, I say #pragma once
| | 03:05 | like that and save and compile,
you'll see there it works just fine.
| | 03:10 | And you are certainly welcome to use this.
| | 03:11 | It's supported by GCC, it's supported
by Microsoft C, it's supported by Apple's
| | 03:17 | LLVM, it's supported by
all of the major compilers.
| | 03:21 | But it is nonstandard, and if you do use
it, then you need to realize that there
| | 03:25 | may be some environments where
your code won't compile yet.
| | 03:30 | And it was actually buggy in some
earlier versions of GCC which may still be
| | 03:34 | deployed on a lot of computers.
| | 03:36 | So my recommendation is always to use
standard C where you can because it's
| | 03:44 | going to be more portable, and
it's going to be better supported.
| | 03:47 | So the include guard is very well supported.
| | 03:49 | It's something that you can type at once or
you can cut and paste at once, and it's done.
| | 03:54 | So it's not really that
much of a burden to include it.
| | 03:57 | But if you prefer, the #pragma once
trick also works in most circumstances.
| | 04:02 | So this is a common
problem with a common solution.
| | 04:04 | You'll see the include guard
solution most often although the #pragma
| | 04:08 | once solution is more succinct and although
it's not standardized, it is widely supported.
| | 04:14 | Now let's delete our working files and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
|
|
5. Data TypesAbout the data types| 00:00 | C and C++ are strongly typed languages.
This means that every value has a specific type.
| | 00:07 | The meaning of a value
is determined by its type.
| | 00:10 | A data type consists both the size
and the interpretation of a value.
| | 00:15 | For example, the int type means a
natural machine-sized integer value that would
| | 00:19 | be 32 bits for a 32-bit machine and
unsigned int means the same size integer
| | 00:24 | with no bit reserved for sign.
| | 00:27 | Built-in types for C and C++ include
integer types for representing integer
| | 00:32 | numerical values, floating point types
for representing real numerical values
| | 00:38 | and the bool type for
representing boolean values, true and false.
| | 00:42 | This type is available on C++, but not in C.
| | 00:45 | C++ also provides constants called
true and false and beginning with C99, C
| | 00:52 | provides a built-in type _Bool and a
standard Header, <stdbool.h> which uses
| | 00:59 | macros to provide bool true and false.
| | 01:02 | This is designed to mimic the
behavior of C++'s bool type without breaking
| | 01:06 | existing code that has traditionally
provided this capability with macros.
| | 01:10 | C and C++ also provide some
compound types, including arrays.
| | 01:15 | An array is a contiguous
sequential set of objects of the same type.
| | 01:19 | C and C++ arrays are very powerful,
flexible and have very low overhead.
| | 01:24 | They are also the basis of C
strings and the C++ STL container types.
| | 01:31 | A structure is a sequential
set of objects of various types.
| | 01:34 | A structure may contain scalars, arrays
and even other structures and classes.
| | 01:41 | C++ classes are based on C structures
and technically a class is a structure
| | 01:45 | that defaults to private membership.
| | 01:47 | In practice a class is a structure that
contains function members as well as data members.
| | 01:51 | We'll discuss these
distinctions later in the course.
| | 01:54 | Classes are available in C++
, they're not available in C.
| | 01:57 | A union is a set of overlapping object types.
| | 02:02 | This allows a single object to hold
objects of different types of different
| | 02:05 | times in the same space.
| | 02:08 | A pointer is a reference to
an object of a given type.
| | 02:11 | The pointer itself typically holds
the address of the object it points to.
| | 02:15 | Pointers are strongly typed in C and C++.
| | 02:18 | The type of a pointer is used as the
type when it's dereferenced, and it's
| | 02:23 | also used to determine the size of
increments, decrements and arithmetic
| | 02:26 | operations on the pointer.
| | 02:27 | C++ also provides a reference type.
This is not available in C.
| | 02:33 | A reference is very much like a
pointer, but with different semantics.
| | 02:36 | The major distinctions between pointers and
references are that references are immutable.
| | 02:40 | Once they're defined, they can not be
changed to refer to a different object.
| | 02:44 | And references are accessed as aliases.
| | 02:47 | A reference is accessed without any
syntactic indication that it's a reference
| | 02:52 | and not directly a variable.
This allows for silent side effects.
| | 02:56 | We'll discuss the C++ reference type
in more detail later in this chapter.
| | 03:01 | Note that neither C nor C++ defines a
special string type, but both languages
| | 03:06 | have provisions for
handling strings of characters.
| | 03:08 | We'll cover both types of
strings in this chapter.
| | 03:10 | C and C++ provide a number of
fundamental data types that may be used or
| | 03:16 | extended for many purposes.
| | 03:17 | Rest of this chapter we'll
cover these types in greater detail.
| | Collapse this transcript |
| Introducing integer types| 00:00 | The integer types are simple fundamental
data types for representing integer values.
| | 00:04 | Whole numbers with no fractional part.
| | 00:07 | The integer types include char, int,
short int, long int, and long long int.
| | 00:13 | Some people pronounce char as chaar.
| | 00:15 | These are all available in
both signed and unsigned versions.
| | 00:19 | The sizes of these types will
vary by compiler and processor.
| | 00:22 | The char type will typically be the
minimum size to contain a character, on most
| | 00:27 | modern systems that's 8 bits.
The char type may be signed or unsigned.
| | 00:32 | All the other integer types are signed
unless modified with the unsigned keyword.
| | 00:37 | The short int type is the smallest natural
size of an integer for the target processor.
| | 00:42 | It may be the same as int,
it may be the same as char.
| | 00:45 | On most modern systems, it's 16 bits.
| | 00:49 | The int type is the natural size of an
integer for the target processor, and on
| | 00:52 | most modern desktop systems, it's 32 bits.
| | 00:56 | Long int is typically double the size
of an int and long long int is either
| | 01:00 | double the size of a long int
or the same size as a long int.
| | 01:04 | Let's take a look at these in code.
Make a working copy of integer-types.cpp.
| | 01:10 | I'm going to paste that into the Working
project and open it up in the editor here.
| | 01:15 | Let's just maximize this so that
you can see what it looks like.
| | 01:19 | Here we are declaring variables in
each of the five integer types, they're on
| | 01:23 | lines 6 through 10, and then on lines
12 through 16, we're displaying the size
| | 01:29 | of these using the sizeof() operator.
| | 01:31 | Then starting on line 18, we play
around with the character a little bit to
| | 01:35 | determine if it's signed or unsigned.
Let's take a look at how this works.
| | 01:40 | Bring this back to size,
and we'll compile and run it.
| | 01:43 | You see there's our sizes.
| | 01:46 | The size returned by sizeof() is in
bytes, so char is 1 byte, short int is 2
| | 01:52 | bytes, and a byte is 8 bit.
| | 01:53 | So, short int is 16 bits, and int is 4
bytes, long int is 8 bytes, and long long
| | 02:00 | int are also 8 bytes.
| | 02:03 | We can see from this that char is
signed on this system and the way we would
| | 02:07 | determine that is by
initializing it with a value of 127.
| | 02:10 | 127 is the largest value that
you can represent in 7 bits.
| | 02:16 | And so if we increment that, we know
that it will set the sign bit, and it
| | 02:20 | will turn into a negative number if
char is signed, and indeed that's what
| | 02:24 | happens, so char is signed.
| | 02:26 | If we try the same thing with an
unsigned char, and I just type in the word
| | 02:30 | unsigned, you'll see, save that, and
run it, that when we increment it, it
| | 02:35 | becomes 128 instead of -128.
So go ahead and put that back, and run it again.
| | 02:42 | Sometimes you get this Launching
Working, you can just say always run in
| | 02:46 | background or do what I do,
just press the Run in Background button.
| | 02:50 | And there we get the -128.
| | 02:53 | So, literal numbers like this are
actually of type int, and in this case, it's
| | 02:58 | getting adjusted to the size of the
smaller space for the character, and that's
| | 03:03 | normal behavior for C and C++.
| | 03:07 | So if I wanted to give a value to the
variable i which is int, I could say
| | 03:11 | 12345, and that would put
the value of 12345 in i.
| | 03:18 | If I wanted to initialize a long int as an li,
I could still use an int to initialize it.
| | 03:24 | But if I wanted to initialize a little
larger value, I'll put a L at the end of
| | 03:28 | it, and that allows me to type a
literal value that's a long int.
| | 03:32 | Two Ls will make it long, long
and a U will make it unsigned.
| | 03:37 | So, if I just do that, it's an unsigned int.
| | 03:39 | If I do that, it's unsigned long, and
if I do that, it's unsigned long, long.
| | 03:45 | So, I'm going to save that
and go ahead and display it.
| | 03:53 | Save that and run it, and you can see
we're getting the value there in the long int.
| | 03:59 | So, C and C++ provide a full
selection of integer types in many sizes both
| | 04:04 | signed and unsigned.
| | 04:05 | Now, let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Understanding floating-point types| 00:00 | C and C++ provide a few
basic floating point types.
| | 00:05 | Let's go ahead and open
floating point types.cpp.
| | 00:08 | I'm going to make a working copy of
that, and paste it into our Working
| | 00:13 | project, and go ahead and open that up,
and we'll double-click on this so we
| | 00:17 | can see the whole thing.
| | 00:18 | C and C++ provide these
basic floating point types.
| | 00:23 | We have float, we have
double, and we have long double.
| | 00:27 | You'll notice that we have some cout
statements here which are listing simply
| | 00:32 | the size in bytes using the sizeof()
operator of each of these different types.
| | 00:37 | So let's go ahead and run this.
| | 00:39 | I'm going to double-click on this to
bring it back to our regular size, and I'll
| | 00:44 | go ahead and click the
green Compile and Run button.
| | 00:48 | You see here the size of float is 4, the
size of double float is 8, and the size
| | 00:53 | of long double float is 16,
and those sizes are in bytes.
| | 00:59 | So for bits, you would need to multiply
that by 8, and so the float size is 32
| | 01:05 | bits which has a precision of about 7 digits.
| | 01:09 | So while it may be possible to
represent some very large or some very small
| | 01:12 | numbers using floating point types, the
precision is always limited by the size
| | 01:17 | of the variable itself.
| | 01:19 | The number of bits that are available
to represent the floating point number.
| | 01:23 | So a 32 bit float is going to have a
precision of about 7 digits, and a 64 bit
| | 01:29 | float which is the double is going to
have a precision of about 16 digits.
| | 01:35 | The long double is a standard IEEE size
which has about 80 bits, at least on GCC it is.
| | 01:43 | On some other platforms, it's simply an
alias for double, like for instance in
| | 01:48 | Visual C++ at least the last time I
checked, long double was the same as double.
| | 01:53 | The thing that you need to remember
about these types is that well, again, you
| | 01:57 | may be able to represent some
very large and very small numbers.
| | 02:00 | The precision is sacrificed.
| | 02:03 | So, for example, if I come down here,
and I will initialize and use some of
| | 02:07 | these, let's say f = 0.1,
then I go ahead and I add to it.
| | 02:12 | I will say f += 0.1+0.1. Now, we would
expect the value to be 0.3, and I'll go
| | 02:21 | ahead and I'll print that out, "f is"
<< f << endl;, and if we go ahead and
| | 02:31 | compile and run this, you
will see it says f is 0.3.
| | 02:35 | Well, here's the interesting thing about this.
| | 02:37 | If I now say if(f == 0.3), and that's
the literal constant 0.3, then I'll go
| | 02:45 | ahead and I'll say cout << "yes" <<,
and if I say else cout << "No" <<, now
| | 02:57 | given that it says f is 0.3, we
would expect to get a yes here, right?
| | 03:02 | And given that I asked that question, or I
maybe expecting something else, the answer is No.
| | 03:07 | Even though it's displaying a 0.3, all
the way out to the amount of precision
| | 03:13 | that it has, it is not
quite exactly equal to 0.3.
| | 03:17 | And we can print it out and show you how many
digits it is but that's not really important.
| | 03:22 | This is one of the lower
precision versions of this that we have.
| | 03:25 | What's important here is for you to
know that if you're doing something that
| | 03:28 | requires actual precision, something
like accounting, it requires a specific
| | 03:32 | number of precision, requires that
rounding be handled in a specific way.
| | 03:37 | And you don't want to be
using floating point numbers.
| | 03:39 | You want to be using one of the integer types.
| | 03:42 | So, C and C++ provide a few standard
floating point types, and while it's
| | 03:46 | possible to represent very large, and
very small numbers with these types, it is
| | 03:50 | at the expense of accuracy,
and you need to be aware of that.
| | 03:52 | Precision is important, as in the
case of accounting, you want to use an
| | 03:56 | integer data type instead.
| | 03:58 | So, let's go ahead and delete the Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with characters and strings| 00:00 | The C String is an array of
characters terminated with a null value.
| | 00:04 | This is sometimes referred to as a C
String or a null terminated string to
| | 00:08 | distinguish it from
object oriented string types.
| | 00:11 | The character type is an integer type
of the size suitable for holding a single
| | 00:15 | character which is 8
bits on most common systems.
| | 00:19 | A string in C is an array of these
characters terminated with the 0 value.
| | 00:25 | So this six character string
takes up seven values in the array.
| | 00:29 | Let's take a look at this in code.
| | 00:32 | Make a working copy of c-strings.cpp,
and we'll paste it here into our Working
| | 00:38 | project, and I'll double-click
on that and open it in the editor.
| | 00:42 | So here we have that same string six
characters long, and this is actually
| | 00:46 | taking up seven bytes inside of the array.
| | 00:49 | see, we print it with cout, and we also
iterate through the array with a for loop.
| | 00:53 | I'm going to add to this right here.
I'm going to say cout << "length of array: " <<
| | 01:01 | and we'll use the sizeof() operator, (c-string) like that.
| | 01:08 | So let's go ahead and compile and run
this, and we'll scroll up to the top.
| | 01:13 | The length of the array is 7, even though
there're six characters 1, 2, 3, 4, 5, 6.
| | 01:18 | The length of array is seven,
because that seventh byte holds the null.
| | 01:22 | So you see this is built into the C language.
I initialize this array like this.
| | 01:27 | I make a character array, and I
initialize it with a literal string, and it's
| | 01:32 | actually adding that null byte to it.
It's putting all seven bytes of that into it.
| | 01:37 | So that literal string is actually a c-string.
| | 01:40 | It's an array of characters with a
null terminator, and that's a built-in
| | 01:44 | paradigm built into the C
language and also of course in C++.
| | 01:49 | So then we print out the string.
| | 01:50 | We see there's the six characters of
the string, and that's line 9 there that
| | 01:54 | cout, and then we print out each of
those characters one by one iterating
| | 01:58 | through with the for loop.
They in lines 11, 12, and 13.
| | 02:03 | So C Strings are very simple form of
strings much simpler than the string class
| | 02:07 | provided by the C++ STL.
| | 02:10 | For circumstances where you don't need
the power of object-oriented strings, C
| | 02:14 | Strings are simple, they're small, they're fast,
and they're very commonly used even in C++.
| | 02:18 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using strings| 00:00 | The C++ string class is not
actually a fundamental type.
| | 00:04 | This is a class from the
standard template library.
| | 00:08 | These objects are very different and
significantly more powerful and useful then
| | 00:12 | C strings, yet in many
ways they work very similarly.
| | 00:15 | It's important to understand the distinctions.
| | 00:17 | Let's go ahead and make a working copy
of cpp-strings.cpp from the Chap05 folder
| | 00:24 | here in our ExerciseFiles, and we'll
paste this into our Working project.
| | 00:30 | Scroll down and double-click on
that so that we can open it up.
| | 00:34 | And here we have a C++ string, you'll
notice that I simply declare it with the
| | 00:40 | string as if it were a type, and this
is standard in the C++ object-oriented
| | 00:46 | model that I can simply put the
name of a class as if we were a type.
| | 00:50 | The design goal of C++ objects was that
they could be used just as you would use
| | 00:54 | any first-class type.
| | 00:56 | And so by including iostream I get
these strings, and I simply declare it and
| | 01:02 | cppstring, and this is a C++
string, and then I can output it.
| | 01:06 | And exactly as I did, this is
exactly the same code that I used in the C
| | 01:11 | string's example, I'm able to
iterate through it as if it were C-array.
| | 01:14 | Let's go ahead and Save this and Run it,
and there we have it this is the C++
| | 01:22 | string, and there is all the
characters in the array, so there's 20
| | 01:25 | characters in that array.
| | 01:27 | And if I go ahead here and say what is
the size of this, and we run that, we see
| | 01:36 | that it says the size is 8, and that
is simply not even close to reality.
| | 01:42 | So we see that it actually works very
differently, it looks similar, and you can
| | 01:48 | use it in many of the same ways.
| | 01:50 | But it's really a very
different animal than the c-string.
| | 01:55 | So I'll go ahead and I'll get rid of that.
| | 01:57 | And let's see some of the
other things we can do here.
| | 02:00 | Now first of all you'll notice that
we're testing for a null byte at the end and
| | 02:05 | the container class that this is based
upon will actually emulate that behavior
| | 02:08 | so that it can be used just like a C-
array, but it's not actually like that, and
| | 02:12 | it's more correct to do something like this.
| | 02:17 | To say, well i is less
than the size of the string.
| | 02:21 | We'll see that this ends up working exactly the
same, but it's just a little bit more correct.
| | 02:26 | So what this is this dot size that's
actually a method in the string class.
| | 02:33 | And when you instantiate this C++ string
object, then you get all of the methods
| | 02:39 | in that class and sizes one
of those methods in the class.
| | 02:42 | Even easier you can use the new C++
for iterator loop, and you can simply say
| | 02:54 | like that, and then obviously you don't
have this i any more, so we'll take that
| | 03:00 | out, and you simply printf c like that.
| | 03:06 | And so, this is a new paradigm in C++11,
this is an iterator loops that's used
| | 03:12 | with the same for keyword, and
you just have any container object.
| | 03:16 | And its fundamental type,
which in this case is c.
| | 03:19 | So C++ strings are a container of characters.
| | 03:23 | And this will work just like this
except without the index numbers to the left.
| | 03:28 | So there is each of the individual characters.
| | 03:30 | So you can actually iterate
through that loop just like that.
| | 03:34 | Of course you can also use C++
iterators, there we go.
| | 03:42 | So that'll get us an iterator from the
beginning, and this auto keyword, this is
| | 03:46 | also new in C++11, this allows us to
not have to type out the very long type of
| | 03:53 | that particular iterator.
| | 03:56 | We compare it to the end, as long as
we're not at the end we can go ahead and
| | 04:03 | iterate through the loop, there we go.
| | 04:08 | So we got a little bit
long there, but there it is.
| | 04:10 | And now we no longer have c here, but what
we have is what's pointed out by the iterator.
| | 04:15 | So the loop ends up looking like that,
and I'll bring this down to size again,
| | 04:20 | and we'll compile and run it, and you
see we get exactly the same result again.
| | 04:24 | So, now we're simply iterating
through the container with an STL iterator.
| | 04:28 | Of course the string class also has a
lot of member functions, and we'll be
| | 04:33 | covering those in the chapter on the STL.
| | 04:35 | But you can see here, this is just
an overview of the C++ string class.
| | 04:41 | You can see the distinction
between these objects in C strings.
| | 04:44 | C strings are very simple, they're very
basic, they're fundamental type in C and
| | 04:48 | C++ string class is much more
rich and has a lot more over ahead.
| | 04:54 | So now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Creating character escape sequences| 00:00 | Some characters in C and C++ have
special meaning or otherwise not normally
| | 00:05 | accessible using the C language character set.
| | 00:09 | Escape sequences are used
to access these characters.
| | 00:12 | Let's go ahead and make a working copy
of char-escape.cpp, and we'll paste that
| | 00:18 | into our Working project
and open it up in the editor.
| | 00:22 | Let's go ahead and press the Compile and
Run button there, and we see This is a string.
| | 00:27 | Now if I wanted to insert in here a
single quote I could use a backslash
| | 00:34 | followed by a single quote,
and that would display it in the string.
| | 00:38 | So I save that and run it.
| | 00:41 | If you get this you can just press
always Run in Background or do what I do
| | 00:45 | just press Run in Background.
| | 00:47 | And we can use a backslash with a double quote
to get a double quote or we can use two
| | 00:52 | backslashes to get a single
backslash or we can use a backslash with a
| | 00:58 | hexadecimal number x40
to get an ASCII character.
| | 01:03 | So I'm just going to save this, and
we'll run it again, and we see that we
| | 01:08 | now have single quote, double quote. We
have a backslash and the @ symbol
| | 01:13 | which is hexadecimal 40 in the ASCII table.
| | 01:17 | You can also get some non-graphical
characters, for example, a \n is a new
| | 01:22 | line, and a \t is a tab.
| | 01:26 | You notice that I put that
right up against the a there.
| | 01:29 | So we'll see what happens.
We'll save that and run it.
| | 01:34 | And you see we have This is and then
tabbing over eight characters for the a,
| | 01:38 | and that's on separate
line because of the new line.
| | 01:40 | You can also put in Unicode
characters if you want to.
| | 01:46 | For example, I can do backslash and the
letter u and 03, b like boys, c like
| | 01:53 | Charlie, and that should
give us a Greek letter Mu.
| | 01:58 | This is a full table of the
standard character escape sequences.
| | 02:01 | You can see that we have the ones that
we've shown, we have a few extras, and we
| | 02:05 | also have down at the bottom there
octal values, hexadecimal values, and single
| | 02:09 | word and double word Unicode values.
| | 02:14 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with qualifiers| 00:00 | Qualifiers are used to change the
default properties of variables.
| | 00:04 | There are two types of Qualifiers in C and C++,
Type Qualifiers and Storage Class Specifiers.
| | 00:11 | This is an example of a
variable declaration with qualifiers.
| | 00:15 | In this example the const and
static keywords are qualifiers.
| | 00:20 | They tell the compiler that this
variable will be immutable, that's the const
| | 00:23 | qualifier, and that it will be
stored in static storage space.
| | 00:28 | There are two types of qualifiers, there
are Storage Class Specifiers, and there
| | 00:32 | are Type Qualifiers.
| | 00:34 | The Type Qualifiers include const
which makes a variable immutable that means
| | 00:38 | its value cannot be changed, and
volatile which marks an objects that may be
| | 00:44 | changed by another process, this is
commonly used for threaded and multi-user
| | 00:47 | applications that share memory.
| | 00:49 | And mutable, this is used to modify a data
member from a const qualified member function.
| | 00:55 | This is only available in C++.
The Storage Class Specifiers include static.
| | 01:01 | Objects stored in static memory have
life beyond the execution of a block.
| | 01:05 | Static variables are commonly used for
keeping state between usages of a given function.
| | 01:11 | Register, register variables
are stored in processor registers.
| | 01:15 | This qualifier is taken as a
suggestion by the compiler.
| | 01:18 | The compiler may or may not
actually store the variable in a register.
| | 01:22 | And extern, extern variables are
defined in a separate translation unit and are
| | 01:27 | linked together at link time.
| | 01:30 | The auto keyword is deprecated it's
actually been removed from the very latest
| | 01:35 | version of C++ and will probably be
removed from future versions of C.
| | 01:40 | The auto keyword was used
to specify a storage class.
| | 01:44 | In C++11 the keyword has been
repurposed as a special type.
| | 01:48 | Even though auto is still a valid
storage class in C, I recommend that you
| | 01:53 | don't use the keyword.
| | 01:54 | Auto storage is as the name
suggests automatic, and there's no need to
| | 01:59 | specify it with a keyword.
| | 02:01 | Let's take a look at a couple
of these qualifiers in code.
| | 02:07 | Make a working copy of qualifiers.cpp,
paste this into our Working project and
| | 02:13 | open it up, and here we've simply
declared an integer, and we're displaying it.
| | 02:17 | I'll compile and run this, and
you see it says the integer is 47.
| | 02:22 | And if I come in here, and I change
the value of the integer to 112, and I
| | 02:30 | compile and run that, you'll
see the integer is now 112.
| | 02:33 | Now if I qualify this as const, and
that makes it a constant variable, which
| | 02:40 | makes it immutable which
means it cannot be changed.
| | 02:43 | And now if I try and compile this,
you'll see that I get an error.
| | 02:48 | And if I hover over that error it
says assignment of read-only variable i.
| | 02:53 | The const qualifier is actually very common.
| | 02:56 | It's commonly used in objects, for
things in the object that should not be
| | 03:00 | changed even accidentally.
| | 03:02 | Another very common
qualifier is the static qualifier.
| | 03:07 | And to demonstrate static I am going to
go ahead and create a little loop here.
| | 03:16 | So in this loop we have two variables,
i is the iterator that's part of the for
| | 03:21 | loop itself and j is an automatic class
variable, remember automatic class still
| | 03:27 | exists, it's just automatic, we
don't need an auto keyword for that.
| | 03:31 | And it's initialized the value 12, and
then we add the value of the iterator.
| | 03:36 | So if I run this, see we have i is 0, j
is 12, i is 1, j is 13 and so each time
| | 03:43 | through j begins at 12, but it
gets this number added to it.
| | 03:47 | So here j is 12 plus 2, 12 plus 3, 12 plus 4.
| | 03:52 | Now if I put the static qualifier
here, now j is no longer an automatic
| | 03:58 | variable, it's not stored in
disposable automatic memory.
| | 04:01 | It's stored in static memory, and it
gets initialized once, but it will continue
| | 04:06 | to accumulate its value, so you'll
see it works very differently here.
| | 04:10 | Now j is 12 plus 0, which is still 12 so
here j is 12 plus 1, here j is 13 plus 2,
| | 04:19 | here j is 15 plus 3 and 18 plus 4.
| | 04:23 | So j didn't get reinitialized to 12
each time through, it's carrying its value,
| | 04:29 | it's being stored in a separate space
where it doesn't get reinitialized each
| | 04:33 | time this loop starts.
| | 04:35 | Static variables are very common for
keeping state and functions and in loops.
| | 04:41 | Qualifiers are used to change
default properties of variables.
| | 04:44 | Some of these like constant static
you'll use frequently. Others are good to
| | 04:48 | know about for when you need
them or when you see them in code.
| | 04:51 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using the C++ reference type| 00:00 | C++ references are very much like pointers,
but with different rules and semantics.
| | 00:06 | A lot has been written about C++
references, and there are many opinions about
| | 00:10 | whether they're necessary or useful or
good or bad, but this much is true, they
| | 00:14 | are here to stay, and you'll need to
understand them in order to use them.
| | 00:18 | So let's make a working copy of references.cpp.
| | 00:21 | We'll paste that into our Working project and
double-click on it to open it in the editor.
| | 00:27 | And let's take a quick look at this example.
| | 00:29 | Here on line 6 we're declaring and
initializing a variable i, it's an integer,
| | 00:35 | and we are giving it a value of 5.
| | 00:37 | And then on the next line, we are
declaring a reference variable, this is of
| | 00:41 | the C++ reference type, and we are calling it
ir, and we're initializing that reference to i.
| | 00:49 | So now ir is a reference to i.
| | 00:51 | So when we set ir and give it a value
of 10, and then we're going to print out
| | 00:57 | the value of i, Now remember we set i
to 5 and our reference got changed to 10,
| | 01:03 | so when we run this, we'll see that i is now 10.
| | 01:07 | You notice this syntax, I don't have to
dereference it, I don't have to put an
| | 01:12 | asterisk or anything in front of it,
I just say ir = 10, and it actually
| | 01:15 | changes the value of i.
| | 01:18 | So reference works very much like a pointer,
but with some significant differences.
| | 01:22 | The syntax of setting a reference is
different and does not involve using the
| | 01:25 | address of operator.
| | 01:27 | So in other words here on line 7, I
don't have to do this, as I would with a
| | 01:33 | pointer, I would have to set it
like that to the address of i.
| | 01:37 | Here I am just setting the reference to equal i.
| | 01:40 | The syntax of getting the value referred
to by a reference also does not involve
| | 01:44 | the dereference operator.
| | 01:45 | So when I want to set or take the
value of it, I don't have to put an
| | 01:50 | asterisk in front of it like that
to dereference it, because it's not a
| | 01:53 | pointer, it's a reference.
| | 01:54 | The whole idea of references is to
make them more transparent, and in some
| | 01:59 | ways to make them safer and in other ways
it obviously also makes them more dangerous.
| | 02:03 | You cannot refer to the reference
itself that is you cannot take a reference of
| | 02:08 | a reference, you can't have a pointer
to a reference, and you cannot have an
| | 02:11 | array of references.
| | 02:13 | And a reference cannot be null, it
cannot be uninitialized, and it cannot be
| | 02:16 | changed to refer to another variable.
| | 02:19 | So in other words, if I were to say ir= j
where j is some other variable, it's
| | 02:24 | really just going to copy the value of
j into i, it's not going to change the
| | 02:29 | reference variable itself.
| | 02:30 | There's no way to change a
reference variable once it's been set.
| | 02:33 | Now a really common usage of this, and
this is actually where you're going to
| | 02:38 | see these things the most
commonly is in functions and methods.
| | 02:42 | So here I am going to declare a function,
I am going to say it's int reference,
| | 02:46 | so it returns a reference to an int,
and we'll just call the function f, and it
| | 02:50 | takes a reference to an int as its argument.
| | 02:55 | And I'm just going to
return the increment of that int.
| | 02:59 | So all it will do is it will take that
integer reference, and it will increment
| | 03:03 | it, and it will return a
reference to the integer.
| | 03:05 | So, I am going to get rid of these things here,
and I am just going to say f and pass it i.
| | 03:11 | Now you notice the way that I called it,
I am just passing it i like I would
| | 03:16 | any other function.
| | 03:17 | And if the function was not taking a
reference then the function would make a
| | 03:21 | copy of i, and it would put it on its
stack, and it would create an automatic
| | 03:25 | variable internally, and it would
increment that and return that value.
| | 03:28 | But instead, it's going to do
something very different here.
| | 03:30 | Notice that we're printing out the
value of i, and when I compile this and run
| | 03:35 | it, you see that i is now a 6.
| | 03:38 | What the function has done is it's
actually incremented i, it's affected
| | 03:42 | something outside of its own scope.
| | 03:44 | And it's done that because we're no
longer calling by value now, now we're
| | 03:48 | calling by reference, and we are actually able
to affect the things outside of the function.
| | 03:53 | This gets even more insidious--if I can use
that word--when I do something like this.
| | 03:58 | I am now assigning a value to what's
being returned by that function and
| | 04:02 | remember what's being returned by
that function is a reference to i.
| | 04:07 | So, what happens here is that i is now 42.
| | 04:12 | And this is commonly how things like
operator overloads are done, and we'll
| | 04:16 | cover that when we get to C++
classes later on in this course.
| | 04:19 | But for now, you need to know that this is
something that can actually be very dangerous.
| | 04:25 | The intent with references was to make
some things easier and to make something
| | 04:30 | safer, but it also made
some things more dangerous.
| | 04:33 | So here's the solution.
| | 04:35 | Every time you use references in a
function, you return references or you pass
| | 04:40 | references, you always want to
declare them as const unless there's a good
| | 04:45 | reason not to, and there will be
times when there's a good reason not to.
| | 04:49 | So if I say const int for the return
type and const int for the passing type,
| | 04:54 | notice what happens here.
| | 04:55 | I am going to save this, and I am going
to compile it, and we are going to get a
| | 05:00 | couple of errors here.
| | 05:01 | First of all, inside of the function
I am no longer allowed to increment,
| | 05:04 | because that's a constant value now.
| | 05:06 | So it's not letting the function actually
impact the variable that was passed to it.
| | 05:11 | And likewise, on the return value I am
not allowed to assign to it, because I'm
| | 05:18 | returning a const int.
| | 05:20 | So in my opinion references should've
defaulted this way, but it's okay we have
| | 05:25 | the qualifier const, and if we just get
into the habit of using it all the time
| | 05:30 | except where we actually intend to
have these side effects, then our code is
| | 05:36 | going to be a lot better, and
it's going to be a lot safer.
| | 05:39 | If you actually want to have side
effects, my recommendation is to use pointers
| | 05:43 | where you can instead of references.
| | 05:44 | And obviously there are a lot of
people who disagree with my opinion on that.
| | 05:48 | You need to be aware that that
there's a lot of code out there that uses
| | 05:52 | non-const references, including
quite a bit of the standard template lib.
| | 05:56 | So you just need to be conscious of this effect.
| | 05:59 | References are very
powerful and very common in C++.
| | 06:03 | We'll be using references quite a bit,
and you will gain much more experience
| | 06:07 | with them in the rest of this course.
| | 06:08 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with structured data| 00:00 | In C the struct keyword provides a way
to aggregate a fixed set of data member
| | 00:06 | into a single object.
| | 00:08 | In C++ struct is expanded to include
function members, that usage will be
| | 00:13 | covered in the classes and objects chapters.
| | 00:16 | In this movie we'll be
dealing with the Standard C struct.
| | 00:19 | Let's go ahead and open struct.cpp I am
going to make a working copy of that and
| | 00:25 | paste it into our Working project,
scroll down and double-click to open it.
| | 00:30 | Let's go ahead and span that to the full
screen so we can take a look at the entire file.
| | 00:37 | Here we have a struct, and we've name
the struct employee, and it has three data
| | 00:42 | members, it has an int, and
it has two character pointers .
| | 00:47 | And then down here in main we say struct
employee, and we give the variable name.
| | 00:54 | So this creates a variable
of the type struct employee.
| | 00:58 | And we initialize that with this
initializer list, and it has these three
| | 01:04 | members 42, Joe and Boss.
| | 01:06 | So that's the employee ID,
and the name, and the role.
| | 01:09 | All right, let's go ahead and compile
and run this, and then we will take a
| | 01:14 | looks at some details.
| | 01:15 | So there we have it runs, in this string
prints out, joe is the boss, and has ID number 42.
| | 01:22 | First thing I'd like to point out here
is the use of the keyword struct here in
| | 01:26 | the declaration, in C this is required,
in C++, and you'll often see at this way
| | 01:33 | you can actually eliminate that,
and this will still compile and run.
| | 01:38 | If I was compiling this with a C
compiler that would not work we'd need that
| | 01:42 | struct keyword there as well.
| | 01:44 | And so I'll leave that in
for now, and it doesn't hurt.
| | 01:48 | In my personal usage I tend to use the
struct keyword and its part of my making
| | 01:53 | a distinction between struct and class.
| | 01:56 | In C++ this is actually a fully first-
class object you can have a function
| | 02:03 | members here as well as data members.
| | 02:05 | In C it doesn't work that way, you
can't have the function members because C
| | 02:09 | doesn't have the object-
oriented extensions that C++ has.
| | 02:13 | And really the only distinction
between struct and class in C++ is that the
| | 02:19 | data members default to being public, in
structures so that they work just like C structures.
| | 02:25 | And in a class they default to being private.
| | 02:28 | So I tend to use struct in places where
I mean just an aggregate of data, and I
| | 02:33 | tend to use it exactly like a C
struck and its works perfectly.
| | 02:37 | And if I really intend to help
function members that I go all the way, and I
| | 02:41 | created a class with private data
members and public function members, and I use
| | 02:46 | the class keyword instead.
| | 02:48 | To really make that distinction that
this is a data structure and not a class
| | 02:53 | with function members.
| | 02:55 | So inside of the struct you can
really have any valid type, I have got two
| | 02:59 | different types, here I've got character
pointers, and I've got an integer.
| | 03:02 | And when you access it you
access it with this dot notation.
| | 03:08 | And so joe.name refers to the name
field inside of the employee structure in
| | 03:15 | the variable named Joe and .role refers to
the role field in dot ID refers to the ID field.
| | 03:24 | If instead I was accessing this view a
pointer and so let me create a struct
| | 03:29 | employee pointer, and I'll go ahead,
and I'll assign that to the address of
| | 03:35 | Joe and so now I have this pointer instead, and
I can do this, ep and use that notation there.
| | 03:43 | And let me just go ahead and duplicate
that across here, and we'll compile that
| | 03:47 | and run it and see that works exactly
the same, you get exactly the same result.
| | 03:52 | And this is a very common idiom, now I
have a pointer that points to this type,
| | 03:57 | and I could have several of these
struct employers, and I could simply assign
| | 04:00 | this pointer loop or however it is I want to
do that, and then I can access them directly.
| | 04:06 | So this pointer dereference operator or
structured dereference operator or class
| | 04:12 | dereference operate
however you want to look at it.
| | 04:15 | That dereference is a pointer and
accesses a field all in one operator.
| | 04:21 | And so that's the dash followed by right angel
bracket, and that's the dereference operator.
| | 04:26 | Now in C and again this works the same way
in C++, but it's more commonly used in C.
| | 04:34 | If you mean to be declaring a lot of
these struct employees, and you don't want
| | 04:38 | to have to type the whole thing each
time, you can do this, you can say typedef
| | 04:42 | struct employee and here you can name
the type, and you can call it employee
| | 04:50 | type or you can even call
employee, and that works just fine.
| | 04:54 | And so then here instead of struct
employee like that I can employee type
| | 04:59 | and I can do the same thing here.
And again that will work exactly as expected.
| | 05:07 | And so this is a away if you're not
using C++, and you want to get around that
| | 05:11 | limitation and not having to
type the word struck every time.
| | 05:14 | I'm not a big fan of typedefs in general,
you know there are times when they're
| | 05:18 | really convenient and handy,
and you want to use them.
| | 05:21 | But most of the times using them in
a circumstance like this, it simply
| | 05:25 | creates more confusion than is necessary, but
that capability is there if you want to use it.
| | 05:30 | So the ability to create data structures
using struct is a fundamental tool in C.
| | 05:36 | And as we learned later it's also the
basis of classes and objects in C++.
| | 05:41 | So let's go ahead and delete our Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Introducing bit fields| 00:00 | Bitfields provide the ability to pack
multiple values into less space than they
| | 00:04 | would normally take.
| | 00:06 | Let's look at an example here in
bitfields.cpp, copy that and paste it into our
| | 00:11 | Working project and open it in the editor here.
I'll just maximize this so that you can see it.
| | 00:16 | So beginning on line 5 you'll see there
is a structure called preferences, and
| | 00:20 | it has five members, four
Booleans and an unsigned int.
| | 00:24 | And you'll notice that each one of
these variable has a little bit of syntax
| | 00:27 | we've not seen before.
| | 00:28 | After the name of the variable
there is a colon and a number.
| | 00:32 | This number represents the number
of bits that that field will occupy.
| | 00:35 | So a Boolean value doesn't require
more than one bit and an unsigned int only
| | 00:40 | requires the number of bits that it
will take to represent the largest number.
| | 00:44 | And very, very few people I imagine
have more than 16 children, so number of
| | 00:48 | children can be in four bits pretty comfortably
for most cases, at least for our purposes here.
| | 00:53 | And you'll notice that down here
beginning on line 15 I initialize this
| | 00:57 | structure, and I just see this true
and false for the Booleans and integer
| | 01:01 | number for the numberOfChildren.
| | 01:03 | And it all behaves exactly like you'd
expect except that the entire structure
| | 01:07 | just requires 8 bits.
| | 01:09 | So let's go ahead and bring this back
down to size and compile it and run it.
| | 01:13 | And you'll see that it
works just as we would expect.
| | 01:16 | So for the true ones like likesMusic
and hasInternet, we see that those get
| | 01:21 | printed because we have
this simple if statement here.
| | 01:24 | And that our test subject homer has 3 children.
| | 01:28 | So be aware that the language does not
guarantee any particular bit ordering or byte packing.
| | 01:33 | So how your data is actually stored in memory is
highly dependent on the target machine architecture.
| | 01:39 | This especially becomes an issue if
you store your packed data in a file and
| | 01:42 | then expect to be able to
read it on a different machine.
| | 01:45 | It's also worth noting that bitfields
can be a source of trouble in concurrent
| | 01:49 | or threaded programming, because all
of the bits in a unit must be read and
| | 01:53 | written at the same time.
| | 01:54 | So let's delete our Working file and run
Clean to get set up for next the lesson.
| | Collapse this transcript |
| Working with enumerations| 00:01 | C and C++ have an enumerated type called enum,
and this is actually a very useful thing.
| | 00:06 | Let's make a working copy of enum.c,
not cpp but c, and we'll paste that into
| | 00:13 | our Working project down here, and
we'll double-click and open that up.
| | 00:17 | enum appeared in C89 or NCC, it
does not actually exist in K&R C.
| | 00:23 | What's really interesting about this is
that while it looks syntactically like a
| | 00:27 | type, and it's even referred to
as a type, it is not really a type.
| | 00:31 | Enumerated names actually work
more like constants than like types.
| | 00:35 | Let's go ahead and maximize this, and
we'll scroll through real briefly for
| | 00:39 | those who are typing along at home.
| | 00:42 | So up here at the top around
lines 4 and 5 you see the two enums.
| | 00:46 | And what this code does is it defines a deck
of cards, and then it lists the deck of cards.
| | 00:50 | But once you have the data for deck of
cards then you can start writing card
| | 00:54 | games and doing things like that.
| | 00:56 | And in order to make these symbolic,
so in my card deck as I initialize it, I
| | 01:01 | can have Ace of Spades, 2 of Spades, 3
of Spades, you know 4 of Hearts, Queen of
| | 01:06 | Diamonds and so that I can use these
symbolic names rather than just numbers I
| | 01:11 | used enums so that they
actually work like constants.
| | 01:14 | Of course I could've defined constant
integers, I could've said something like
| | 01:17 | const int Spade = 0, and then I
could've used you know Spade in here.
| | 01:25 | But being able to do them as
enums it allows me to categorize them.
| | 01:29 | So these are suits and these are ranks,
and it just makes it that much more
| | 01:33 | neater and tidier, and that
much more self documenting.
| | 01:36 | So I really don't need a lot of comments
in here at all, and I may not have any.
| | 01:41 | That's right, I don't have any.
| | 01:43 | And yet you can read this code, and
you can know exactly what it does.
| | 01:46 | And that's because of the use of
constants for these strings and the enums for
| | 01:53 | those symbols there.
| | 01:54 | So, let's go ahead and put this back
down to size and go ahead and save it--
| | 01:58 | because I did--I typed in there a
little bit, and I took it out, but it
| | 02:03 | still needed to be saved.
And so I'll compile and run it.
| | 02:06 | And you'll see that all this does is it
defines that deck of cards, and then it
| | 02:10 | just iterates through it, and it
lists the entire deck of cards.
| | 02:13 | I've got Spades, Hearts, Diamonds and
Clubs in order, and I've got the Ace
| | 02:17 | through Jack, Queen, King also in order,
and I was able to do that because of
| | 02:22 | the way that I defined these.
| | 02:24 | So, when you define an enum the first
element is going to get a value of zero,
| | 02:28 | the second element is going to get a
value of one and so on and so forth.
| | 02:32 | Instead you can assign them, different places.
| | 02:34 | And so if I assign this Ace to a 1 and
then this Jack to 11, Queen is going to
| | 02:40 | be 12 and King is going to be 13 automatically.
| | 02:43 | And so when I go in here, and I
maximize this so you can see it.
| | 02:48 | When I come in here, and I start to
initializing my card deck, you see I've
| | 02:52 | got a structure called card_t, card type, and
it has two elements has the rank and the suit.
| | 02:59 | And so for each of these elements of
the array, the array is an array of cards
| | 03:03 | types, and so for each of these
elements the array I have a rank and a suit and
| | 03:07 | a rank and a suit and a rank and a suit.
| | 03:09 | And this is how you initialize an array
of structures like that with the curly
| | 03:14 | braces for each element.
| | 03:15 | And so it makes it all very obvious
exactly what it is and so the enums help
| | 03:21 | to make that happen.
| | 03:22 | In C++, and let me go ahead and I'll
delete this one, and we'll Clean the
| | 03:29 | project, we don't have any problems
with that, and we'll bring in the C++
| | 03:34 | version just copy that and paste it into
the Working project and double-click on it.
| | 03:40 | And again this is very, very similar.
It's pretty much the same code.
| | 03:43 | I'm doing the same thing with
the card deck initialization.
| | 03:46 | One thing that you need to be aware
of is that this type of initializing a
| | 03:51 | structure in C++ actually was not fully
supported by the standard until C++11.
| | 03:58 | And so even though this works in C
it would not have worked in C++ until
| | 04:02 | the latest standard.
So I'm still using the enums.
| | 04:06 | In fact, you know I'm using constant
strings for the strings that get displayed.
| | 04:10 | But I am still using the enums here
because it's just a very convenient thing.
| | 04:14 | And so even though there are some other
ways to do some of these things in C++
| | 04:19 | and the rest of this code is almost
exactly the same, it's still very common and
| | 04:23 | useful to use enums for this kind of a purpose.
| | 04:26 | Let's go ahead and compile and run this,
and you can see that it does exactly
| | 04:30 | the same thing in C++ that it does in C.
| | 04:33 | And now we'll delete our Working file and run
Clean to get it set up for the next lesson.
| | Collapse this transcript |
| Using unions| 00:00 | A union is a data structure that
allows you to use the same memory space
| | 00:04 | for different types.
| | 00:06 | Let's make a working copy of union.cpp
and paste it in our Working project, open
| | 00:12 | it up here, I am going to
maximize it so that you can see.
| | 00:14 | And you'll notice here that we have a
structure except instead of the structure
| | 00:18 | keyword it uses the union keyword,
and within it there's a struct, and that
| | 00:23 | struct represents one element, and it
has four elements inside of it, and then
| | 00:28 | there is also an integer. So the union
has two members, the struct is one of the
| | 00:33 | members of union and the
struct itself has four members.
| | 00:36 | I am using these type names out of standard int.
| | 00:38 | And the purpose of this is is that I
want them to be in a specific size, because
| | 00:43 | of the way that I am using this union.
| | 00:45 | What I am using this union for is I
want to pack and unpack IP addresses and an
| | 00:50 | IP address is 32-bits, and
it contains four 8-bit fields.
| | 00:52 | And each one of those
fields is a separate number.
| | 00:55 | And so this makes a convenient way for
me to use that IP address either as four
| | 00:59 | separate objects or as one object.
| | 01:01 | And those were separate objects and need to
occupy exactly the same space as the one object.
| | 01:05 | So this is actually a really
common solution to problems like this.
| | 01:09 | So here I'm declaring a variable of my
union, my union is called ipv4 and my
| | 01:13 | variable is called addr.
| | 01:15 | And I initialize the bytes field, now
the bytes field is the structure inside
| | 01:20 | the union, so addr.bytes, and I
initialize that with the four separate
| | 01:24 | components of an IP address, and then
I print it out both as the dotted quad
| | 01:29 | notation with the four separate
fields, and as the equivalent integer.
| | 01:33 | So let's go ahead and run
this and see how it works.
| | 01:35 | And there we have it, we have the
dotted quad version of the IP address,
| | 01:41 | 192.168.0.96, and we have the integer.
| | 01:46 | And you'll notice that the
integer has the bytes in reverse order.
| | 01:49 | And that's fine, that's actually correct.
| | 01:52 | So unions are often used to conserve
space in data structures, reuse space for
| | 01:57 | various purposes that are
not needed in the same record.
| | 01:59 | They are also sometimes used for
crude polymorphism as we see here.
| | 02:03 | You need to be careful, using a
union often means that you need to take
| | 02:07 | responsibility for type
checking yourself, and because of this
| | 02:09 | unions are rarely used when
C++ objects are available.
| | 02:13 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Defining types with typedef| 00:00 | The typedef keyword may be used to
provide an alias for a type name.
| | 00:04 | This can be handy in instances where a
type declaration becomes cumbersome, or
| | 00:09 | it may vary on different target systems.
| | 00:11 | Let's go ahead and make a working
copy of enum.c and I'll paste that into our
| | 00:18 | Working project and open that up.
I am going to maximize it here so we can see it.
| | 00:24 | And I'll just scroll through it real slowly
so that those who are typing along at home.
| | 00:28 | This is just a program that defines a
deck of cards and prints them all out.
| | 00:37 | It's a lot simpler than it looks, it's a
lot of typing but that's mostly because
| | 00:40 | there's 52 cards in the deck.
| | 00:43 | Here I've defined this structure called
card, and it has the rank and the suit.
| | 00:49 | And this array is an array of those
cards, so it has rank, suit, rank, suit,
| | 00:54 | rank, suit, and there's 52
pairs of ranks and suits.
| | 00:58 | And so rather than having to type out
struct card here and struct card here, I
| | 01:03 | decided to create a typedef and so it's
card_t, and it's traditional to put _t
| | 01:10 | at the end of a name that's a typedef,
and that way people know to search for a
| | 01:14 | typedef and the source
code to find out what it is.
| | 01:16 | And here in Eclipse obviously if I
just hover over one of the uses of card_t,
| | 01:21 | you'll see that it brings up that
typedef, and I can see what that looks like,
| | 01:25 | and really how to use it.
| | 01:27 | So it's really just a shorthand
facility typedef, and it's just a convenience.
| | 01:31 | But it can be very convenient,
especially in C++ when you start working with
| | 01:36 | iterators and some of those types can
get very, very long and a lot of typing.
| | 01:40 | So the typedef facility can be very
convenient for simplifying cumbersome type
| | 01:44 | definitions and machine dependent types.
| | 01:47 | It's not as widely used in C++ where
other more powerful features may displace it.
| | 01:52 | But it is still very common, and there are
plenty of circumstances where it's useful.
| | 01:56 | So I am going to go ahead and delete
this from the file system, and we'll run
| | 02:03 | Clean to make sure we are set up for the next lesson.
| | Collapse this transcript |
| Introducing the void type| 00:00 | The void type has special meaning in C
and C++ where it's used to specify no
| | 00:05 | value for function
returns and function parameters.
| | 00:09 | Let's go ahead and make a
working copy of void-type.cpp.
| | 00:12 | I'll paste it here into the
Working project and open it up.
| | 00:16 | Here on line 5 we have a function
declaration, and this function returns a void
| | 00:21 | type and takes a void type for its argument.
| | 00:24 | We have the definition of it down here,
and you'll notice that it doesn't actually
| | 00:28 | return anything, and it
doesn't actually have an argument.
| | 00:33 | So this is the primary meaning of the void type.
It's not used for variables.
| | 00:38 | You can't create a variable of void type.
| | 00:40 | You can't assign any value to it, you
can't take any value from it, and that's
| | 00:44 | actually what it means.
| | 00:46 | It's really only used for
function parameters and function returns.
| | 00:51 | So if we save this and run it, you
notice it has the void-type.c, and then it
| | 00:58 | runs the function and says this in his func.
So that's the void type.
| | 01:02 | There's another special usage of the
void type, and this is for void pointers.
| | 01:07 | We'll go ahead and we'll close this,
and we'll delete it from the Working
| | 01:11 | project and run Clean, and then we're
going to open a void-pointer.c.
| | 01:18 | We'll get to void-pointer.cpp in a few minutes.
| | 01:21 | We're going to copy that and paste it
into our project here and double-click on it.
| | 01:26 | I am going to go ahead and
maximize this so that you can see it.
| | 01:29 | Here we have again a function
declaration, and this function returns a pointer
| | 01:34 | to void, and it takes a
pointer to void as its argument.
| | 01:38 | Here's the definition here.
| | 01:40 | You pass it this pointer, and it returns
the pointer and they both have this void type.
| | 01:46 | So what the void pointer means in C and C++--
| | 01:51 | although it's a little more
complicated in C++ we'll get to that in a minute--
| | 01:55 | but what the void pointer means in C
is that this is a pointer, and I don't
| | 01:59 | know, and I don't care what type it is.
| | 02:01 | So you see here that we do a character
pointer with a string, and we pass that
| | 02:06 | character pointer into the void
pointer function, and the void pointer then
| | 02:11 | returns that same pointer, and
it returns it as an int type.
| | 02:16 | Then we're going to print out the 08
hexadecimal digits of what is pointed at
| | 02:23 | by this void pointer.
| | 02:24 | So it's actually going to print
out this string, but in hexadecimal.
| | 02:28 | So let's go ahead and we'll bring this back
down to size, and we'll compile and run it.
| | 02:32 | And you see 34333231, and that's
because the byte order of the Intel processor
| | 02:41 | is backwards, but what we've got there is 1234.
| | 02:44 | So in hexadecimal that would be 31323334,
and that's what's being printed out.
| | 02:53 | So again looking at this we have a
character pointer, we pass that character
| | 02:56 | pointer into the function, and then the
function takes that character pointer as
| | 03:02 | a void pointer and
returns it also as void pointer.
| | 03:06 | Then we take it back from the function,
and we're assigning it to an integer
| | 03:10 | pointer and then printing it out as
a hexadecimal value of that integer.
| | 03:15 | So we're taking that character pointer,
and we're using it as an int pointer all
| | 03:20 | through this void pointer function.
| | 03:22 | So void pointers are
basically a polymorphic pointer.
| | 03:26 | Now we're going to look
at how this works in C++.
| | 03:29 | C++ is a lot stricter about how this works.
| | 03:32 | So I'm going to go ahead and I'm going
to delete this and run Clean, and then
| | 03:38 | we are going to take void-pointer.cpp and
paste it into our Working and open it up.
| | 03:45 | You see the difference here is
really just about how strict it is.
| | 03:49 | When I pass that character pointer
into the function, I actually have to cast
| | 03:53 | it as a void pointer.
| | 03:55 | And when I take the integer pointer
back from the function I actually have to
| | 03:59 | cast it as an integer pointer.
| | 04:01 | Let's go ahead and compile and run this,
and you see it compiles and runs it has
| | 04:05 | exactly the same result.
| | 04:06 | But if I were to take these casts and
remove them and make it look just like
| | 04:11 | our C version, you notice right away I get this little
bug symbol, and it says Invalid arguments.
| | 04:17 | Candidates are void pointers.
| | 04:19 | If I try to compile this,
I get all kinds of errors.
| | 04:22 | I get an error up here saying that I
initialize the argument 1 wrong, and I get
| | 04:28 | these errors here, Invalid conversion
from void pointer to int pointer, invalid
| | 04:33 | arguments conversion from const
void pointer to point pointer.
| | 04:37 | So all of these errors are
mitigated by simply casting.
| | 04:41 | So when I save this and
compile it all those errors go away.
| | 04:45 | So C++ is a little bit more strict
about how you pass around these types, and
| | 04:49 | that's actually a good thing.
| | 04:51 | It helps to prevent you from making
some costly mistakes and the use of void
| | 04:55 | pointers in C is actually a place
where it's really easy to make some very
| | 05:00 | costly mistakes and have a lot of
debugging on your hands while you're trying to
| | 05:04 | figure out, why this thing doesn't
look the way that it's supposed to look.
| | 05:08 | So while void is syntactically a type,
it's only used in special circumstances.
| | 05:13 | Its value is return type or is a
parameter type is to enforce a rule preventing
| | 05:18 | use where value would be expected.
| | 05:21 | And its meaning as a void
pointer is different yet again as a
| | 05:24 | polymorphic type-less pointer.
| | 05:27 | So let's go ahead and delete this Working file,
and we'll run Clean to get ready for the next lesson.
| | Collapse this transcript |
| Understanding the auto type| 00:00 | The auto type is actually a new feature
in C++, but I'm covering it here because
| | 00:05 | it's quickly becoming very common.
| | 00:07 | So we're going to start by making a
copy of working.cpp, and we'll paste that
| | 00:12 | into our Working project and open it up here.
| | 00:16 | And I'm going to add
another include header here.
| | 00:23 | This one is called typeinfo, and
you'll see what that's for in a moment.
| | 00:26 | And we're going to define a simple function.
| | 00:33 | We're going to define a variable, and we're going
to give it a type of auto, auto x = func();
| | 00:39 | like that, and then we're going
to display what's returned by that.
| | 00:47 | And this will all make sense in a moment.
| | 00:49 | And we're going to also look at the type,
we're going to inspect the type with typeid.
| | 00:56 | The typeid is actually an operator
that returns a typeinfo object, and that
| | 01:04 | typeinfo object has a method called name.
| | 01:07 | And that'll tell us the name that the
compiler uses internally for this type.
| | 01:12 | So it's not going to necessarily be the
name that you're used to seeing for, and
| | 01:16 | it's also not necessarily going to be
the same name on your system as what you
| | 01:20 | see on my system, but it should give
us a good idea of what's going on here.
| | 01:24 | So I'm just going to save this and run it,
and you'll notice that we get two things.
| | 01:28 | We get a 42 because our function
returned 42, so our variable got the value of
| | 01:32 | 42, and we're displaying 42 here.
| | 01:35 | And typeid tells what type this variable
is, and it says its i which is integer.
| | 01:41 | So what the auto type does is it
declares an object of a type, and it determines
| | 01:48 | that type by how you initialize it.
Now the object is still strongly typed.
| | 01:53 | That x is now an int, and I can't use it
as a string or use it as a float or use
| | 02:00 | it as something else.
It's always going to be an int.
| | 02:04 | What happened here is really exactly
the same as if I had typed int like this,
| | 02:08 | and if I save this and run it,
you'll see we get exactly the same result.
| | 02:12 | On the other hand, by using auto, I can
change this function, and I can have it
| | 02:16 | return a string, which is an STL object, right.
And I'll just give it something to return there.
| | 02:23 | And I don't need to change anything down here.
| | 02:26 | I just save this and run it, and now
we have a string, and you'll notice
| | 02:30 | that the typeid returned Ss, it may
be something else on your system, but
| | 02:36 | it's a different type.
| | 02:37 | And that type is now a string.
| | 02:39 | So this auto is now exactly the
same as if I had typed string here.
| | 02:43 | And if I save that and run it,
you'll see we get exactly the same result.
| | 02:48 | All auto does is it allows you to
declare a variable when you don't know the
| | 02:54 | type that you need it to be, but however
you initialize it will determine that type.
| | 02:58 | Now this is just a demonstration
of what it is and how it works.
| | 03:02 | This is not how you're actually going to use it.
| | 03:05 | But I'm going to give you an example
here of how you may actually use this, so
| | 03:09 | I'm just going to delete these things,
and I'm going to delete our little
| | 03:12 | function, and I'm going to
change typeinfo to vector.
| | 03:16 | And we're going to use an
STL object called vector.
| | 03:19 | And again, you'll learn about these
later in our chapter on the STL, but I
| | 03:23 | want to show you an application for this,
we're actually going to see auto types really used.
| | 03:27 | So we're going to declare a vector,
and it's going be a vector<int>.
| | 03:31 | So vector is very similar to an array,
only different and more powerful.
| | 03:36 | And we're going to call it i, and we're
just going to give it five members here.
| | 03:43 | And I'll put an equal sign there, it's not
actually required, but I like it, it makes it clear.
| | 03:49 | And now I'm going to iterate through
this vector with a for loop and here's
| | 03:53 | where this gets exciting.
| | 03:57 | I'm going to declare an iterator,
I'm going to call the iterator it, and
| | 04:03 | we'll assign it to i.begin, and this
will be while it != i.end, and we'll
| | 04:13 | increment the iterator.
| | 04:16 | I'm just going to maximize this while
I type so you can see the whole thing.
| | 04:24 | So what we have here is this iterator,
and you see that's a lot of typing, and
| | 04:28 | it's prone to error, and it's ugly.
| | 04:31 | And the rest of this isn't so bad, so
we'll bring this back down, and we will
| | 04:36 | compile it and run it, and there's the
result that we get and so we're basically
| | 04:41 | iterating through this vector of all
five of these values and 1, 2, 3, 4, 5,
| | 04:46 | they're each one aligned exactly as we expect.
| | 04:48 | Now instead of all of this, when
you're dealing with the STL, and when you're
| | 04:52 | dealing with templates, this
is not a worst-case example.
| | 04:57 | These can get a lot worse than that.
| | 04:58 | I can just type auto, and now it's
really clean and really clear, and it's
| | 05:02 | obvious what it is that I'm doing,
because if I know the STL, I know that begin
| | 05:07 | and end and container
objects always return an iterator.
| | 05:11 | And so here I have an iterator, and I
know that it's typed vector<int> iterator
| | 05:16 | because that's what this returns.
| | 05:17 | So I can just save this and run it,
and I get exactly the same result.
| | 05:22 | So this is actually I think more clear,
it's more readable, and it's a lot less
| | 05:27 | prone to error in both typing and in reading.
| | 05:30 | So this auto feature is a real improvement,
but it's not without its dangers. Be careful!
| | 05:35 | Only use auto types where the
implications are clear and the usage is concise.
| | 05:40 | Otherwise, you could potentially
sacrifice readability and even introduce errors
| | 05:44 | that could be hard to find.
| | 05:46 | So let's go ahead and delete our working.cpp,
and we'll run Clean to prepare for the next lesson.
| | Collapse this transcript |
|
|
6. OperatorsExploring the assignment operator| 00:00 | The assignment operator is
represented by the equal sign.
| | 00:04 | It is used for assigning values to variables.
| | 00:07 | Let's make a working copy of working.cpp
from the Chap06 folder, and we'll paste
| | 00:13 | that into the Working project
and double-click to open it.
| | 00:18 | So assignment operator basically
works like this, if we have a couple of
| | 00:21 | variables we'll just create
some integers called i and j.
| | 00:25 | I can assign value to one of them and
then when I look at it I could say and
| | 00:32 | compile this and run it.
| | 00:34 | And we have assigned a
value to i, it says value is 5.
| | 00:37 | We have this little warning here,
because we're not using j, unused variable j,
| | 00:41 | we'll use it in a minute.
| | 00:43 | So the assignment operator is the equals
sign and what it does is it copies a value.
| | 00:49 | What it's doing in this case is it's
taking the literal value 5 which we just
| | 00:54 | typed in with the number 5, and it's
making a copy of that value and putting
| | 01:00 | it in the variable i.
| | 01:01 | So in this context it's
operating in its copy mode.
| | 01:06 | The assignment operator actually has
two modes, we're going to talk about
| | 01:09 | the copy mode first, and we'll talk about
the initialization mode in a little bit here.
| | 01:13 | So another use for it is we can
assign i to j, so this copies from the
| | 01:18 | right-hand to the left-hand side.
| | 01:20 | In this case it's taking the value that
is in i, and it's making a copy of that
| | 01:25 | and putting it in j.
| | 01:26 | So let's change this to say i is that, and
we'll make another one that says j is that.
| | 01:33 | Now we save that and run it, we
see that they're both the same value.
| | 01:39 | You can also use the assignment
operator to chain assignments.
| | 01:43 | So if we make a third one called k, I
can say k = j = i, and I can even take
| | 01:49 | out this assignment of i, and then they
will all have that same value, so I can
| | 01:55 | compile and run it.
| | 01:56 | And this works because the assignment
operation actually returns the value of the assignment.
| | 02:02 | So this makes it possible
to chain these operations.
| | 02:06 | Some of these distinctions that
we're making right now may seem very
| | 02:08 | technical and very pedantic.
| | 02:10 | The reason we're making these
distinctions is that they're actually going to
| | 02:13 | become important when we start
overloading operators in a later chapter.
| | 02:17 | So just for now understand that the
reason we can chain these assignments is
| | 02:22 | because the assignment operation
actually returns a value, and that will
| | 02:26 | become important later.
| | 02:27 | So the assignment operator actually
works with structures as well, so if we
| | 02:31 | create a little structure here, and we
can create it out here and say struct s,
| | 02:36 | and maybe it's just got a couple
of ints in it, int I, int j, int k.
| | 02:42 | And then down here we can create
a variable with that structure.
| | 02:49 | And so we've created a variable s1
that's of type struct s, and it has the
| | 02:55 | three values in it 1, 2 and 3 and
those are assigned respectively to the
| | 02:59 | structural members i, j and k.
| | 03:02 | And so if we do a little printf here, and
then we can look at those structure members.
| | 03:08 | I'm a big fan of copy and
paste for stuff like this.
| | 03:14 | We'll put in a new line at the end of
our printf format and a semicolon at the
| | 03:20 | end probably will be a good idea.
| | 03:21 | So now when I save this and run
it we have the i, j and k values.
| | 03:26 | So this is actually the other
usage of the assignment operator.
| | 03:31 | In this case it's actually
being used for initialization.
| | 03:34 | So that equal sign is really the
initialization operator in this case as
| | 03:38 | opposed to this assignment operator.
| | 03:39 | We're going to go ahead and do some
assignment with this as well because we can
| | 03:43 | declare a couple of other
structs of the same type, s2 and s3.
| | 03:49 | And we can actually assign s3 = s2 = s1,
| | 03:54 | and again the assignment operator
will copy the entire contents of s1 into
| | 03:59 | s2 and then return that structure so that it
can copy the entire structure of s2 into s3.
| | 04:08 | And so I can make a couple of more
copies of this, and I can say s2 and s3 and
| | 04:16 | come over here and say s2, and I'm just
going to copy and paste and s3 and copy
| | 04:24 | and paste, and you'll see that
they all have exactly the same values.
| | 04:27 | Save that and run it, and that's
because that assignment operator here is
| | 04:32 | actually making copies, and it's
operating in that same chain mode again.
| | 04:36 | So this distinction between
initialization and assignment, this usage here in
| | 04:42 | line 12 is initialization, and it's
taking those values and its initializing
| | 04:47 | s1 with those values.
| | 04:49 | And the usage on line 14 here is
assignment, where it's actually making a copy
| | 04:55 | of the entire structure s1 and putting
it in s2 and then making a copy of the
| | 04:59 | entire structure of s2 and putting it in s3.
| | 05:02 | So those distinctions become more
important later, but for right now for the
| | 05:06 | purposes of C specially, you can
simply think of it as assigning a value from
| | 05:10 | the right-hand side of the equals
sign to the left-hand side of this equals
| | 05:13 | sign, even in the case of initialization.
| | 05:16 | So semantically an assignment operator
simply copies an object from right to
| | 05:20 | left, may be used for
initialization or for copying values.
| | 05:24 | This distinction becomes more important
when using classes with overloaded operators.
| | 05:28 | Operator overloading is
covered later in this course.
| | 05:31 | So let's delete our Working file here,
and we'll run Clean to get ready for next lesson.
| | Collapse this transcript |
| Using arithmetic operators| 00:00 | C and C++ provide a number of
standard arithmetic operators.
| | 00:05 | Let's make a working copy of
working.cpp from the Chap06 folder.
| | 00:10 | We'll paste it here into our
Working project and open it up.
| | 00:14 | I start out by declaring a couple of
integers here, and we're going to just
| | 00:18 | replace this cout with a printf,
because that's just little easier for some of
| | 00:21 | these things, and I can put the
arithmetic operation right in here.
| | 00:25 | I can say i + j, and I'll say the result is,
and it'll come up with a 47. There it is 47.
| | 00:34 | So this is just a simple
case of integer arithmetic.
| | 00:37 | I'm adding two values, and
I'm using the addition operator.
| | 00:42 | I could use the subtraction
operator, and I'll get a negative value.
| | 00:47 | I think this will come out
at -37 if I am not mistaken.
| | 00:50 | There we go -37, because I'm
subtracting a larger value from a smaller value.
| | 00:57 | We can do multiplication, and I'm not
going to try and do this one in my head.
| | 01:01 | Save that and run it, and we get a value of 210.
| | 01:04 | And we can do division, and I'm
actually going to do the division in the other
| | 01:09 | way, because this will
work better for this purpose.
| | 01:12 | So 42 divided by 5, now I believe this
will give me a value of 8 and the reason
| | 01:18 | for that is that we're
working integer arithmetic.
| | 01:22 | So it gives me a value of 8, and
there's also a remainder, and I can get the
| | 01:25 | remainder with the modular operator,
and that remainder should be 2.
| | 01:30 | So I'll run that, and there the remainder is 2.
So those are the five basic functions.
| | 01:36 | We have addition, subtraction,
multiplication, division, and remainder or modulus.
| | 01:42 | Now all of these with the exception of
the modular operator are also available
| | 01:47 | for floating points.
| | 01:48 | So if I just declare these as floats,
and I'll start with an addition, and let's
| | 01:54 | give them a fractional part 5.1 and 42.2.
So I'll run that, and you notice we get
| | 02:02 | this large integer, because I'm
interpreting it as an integer.
| | 02:05 | We also have a warning over here that says
it expects int, and we got a type of double.
| | 02:11 | float gets promoted to double
when it's used with printf in C++.
| | 02:14 | So I'm just going to say f there instead,
and we'll run it, and we get 47.29999.
| | 02:24 | So we get some nice
rounding errors there as well.
| | 02:26 | That's actually to be expected with float.
| | 02:29 | If we make this double we have a lower
chance of having that happen, and there
| | 02:36 | we go 47.3000.
We can do the same thing with subtraction.
| | 02:41 | I'm going to save that and run it,
and we get a subtraction result, and multiplication.
| | 02:45 | Save it and run it, and we get a 215.
22 and division 8 blah, blah, blah.
| | 02:55 | And in fact with the floating point we
can do division, and we can expect to get
| | 02:59 | a reasonable result in the other
direction, and we get a fractional part.
| | 03:04 | Of course, the modular operator
does not have any meaning in this case.
| | 03:08 | So if we try to run that we get an
error that says that the binary operator
| | 03:13 | modulo does not apply for double to double.
| | 03:17 | There're also unary versions
of the plus and minus operators.
| | 03:22 | So I'm just going to comment it out i
here, and we'll just take j, and if I
| | 03:28 | put a unary - in front of it, we'll
get -42.2. And if I put a unary plus +
| | 03:34 | in front of it, we'll get a positive 42.2
which is the same as what it is by itself.
| | 03:40 | So the unary + in most contexts
is semantically null, and it's very
| | 03:45 | rarely actually used.
| | 03:47 | There is another use of the
binary version of the plus operator.
| | 03:52 | And in STL containers like the string class.
| | 03:56 | If I say string "This is a string";,
and we'll call that one s1, and if I say
| | 04:03 | string s2 = "This is another string".
| | 04:07 | So we'll to use the cout for this, and
I'll say cout s1 is, and we'll do the
| | 04:15 | same thing for s2, and then we will add
them together, we'll concatenate them.
| | 04:20 | So I will call this
concatenate, and that's s1 + s2.
| | 04:25 | So go ahead and save this and run it.
| | 04:29 | So string1 is This is a string, string2
is This is another string, and you see
| | 04:33 | the concatenation This is a string and
then the second string is jammed right on
| | 04:38 | the end of it there, and that's
another use of the plus operator.
| | 04:42 | So this is really an example of an
operator overload and in the case of the STL
| | 04:46 | container it is a very, very common
usage which is why I'm covering it here and
| | 04:50 | for some of your own containers that
you might define that you might want to
| | 04:54 | also overload the plus operator, and
we'll show you how to do that in the
| | 04:57 | chapter on the classes.
| | 04:59 | So the arithmetic operators in C
and C++ are simple and effective.
| | 05:02 | They work with all the basic types and
can be overloaded for used with C++ classes.
| | 05:07 | We'll cover operator
overloading in a later chapter.
| | 05:10 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with increment and decrement operators| 00:00 | C and C++ provide unary operators for
incrementing and decrementing values.
| | 00:06 | Sometimes these operators are called
increase and decrease operators and they
| | 00:10 | increment or decrement a value by one.
Let's take a look at how this works.
| | 00:14 | We'll make a working copy of working.cpp
out of the Chap06 folder in your ExerciseFiles.
| | 00:21 | I am going to paste this into our Working
project and double-click on it to open it up.
| | 00:25 | I am going to start by creating an
integer i, and we'll give it a value 12, and
| | 00:30 | we'll go ahead and print out that
value, I am going to use printf for this
| | 00:33 | because it's a little more convenient.
So we'll save that and compile and run it.
| | 00:40 | When you get this you can sometimes
just say Always run in background.
| | 00:44 | I just click on the button there.
It just happens sometimes,
| | 00:48 | it may or may not happen on your
screen, it's nothing to worry about.
| | 00:53 | So it says here that the value is 12
and so now if I increment the value I am
| | 00:56 | just going to come down here on the next
line, and I am going to say ++i; and so
| | 01:01 | what that does is it increments the value.
| | 01:03 | Now when we print it out
it will say value is 13.
| | 01:06 | So I'll save this and run it,
and it says value is 13.
| | 01:10 | Now the beauty of the increment
operator as opposed to just assigning a new
| | 01:15 | value, if I were to say i=i+1,
that's really two separate operations.
| | 01:21 | It performs this addition, and then it
copies that value and assigns it into i.
| | 01:27 | So obviously Compiler will probably
optimize that down, and it may not actually
| | 01:32 | make any difference in clock cycles,
but it is more complicated, and it is
| | 01:37 | semantically doing a different thing.
| | 01:39 | The increment operator is
incrementing that variable in place.
| | 01:44 | But the real beauty of this is that I can
increment and print it all in one operation.
| | 01:50 | This actually returns that incremented value.
So if I do this, I'll get the value as 13.
| | 01:56 | Save and run, it says the value is 13.
| | 02:00 | And if I do three of these I'll get 13, 14,
and 15, save and run, 13, 14, and 15.
| | 02:09 | There's another interesting aspect
to this which is that I can put the ++
| | 02:13 | after the i and instead of incrementing it
first it'll increment it after it returns the value.
| | 02:21 | So if I save this and run
this I'll get 12, 13, and 14.
| | 02:25 | So what this is doing is it's
actually returning the value first and
| | 02:29 | then incrementing it.
| | 02:31 | So it returns the value which is 12,
and then it increments it so now it's 13
| | 02:34 | and then in the next printf it
returns the value which is 13, and then it
| | 02:39 | increments it to 14, and on and on and on.
| | 02:42 | So this is called prefix and postfix
versions of the increment operator.
| | 02:47 | In the prefix version, increments
the value and then returns the value.
| | 02:51 | In the postfix version it returns the
value and then increments the value, very
| | 02:56 | simple, very intuitive, and very useful.
| | 02:59 | Of course this also works on floating
point values, so if I define this as float
| | 03:05 | we now have a floating value.
| | 03:08 | So I'll change these to float, and we
should get 12.0 and 13.0 and like that.
| | 03:15 | Save that and run it, and
interestingly it also works with pointers.
| | 03:20 | Now this is a little bit more involved,
but it's tremendously useful, and it's
| | 03:25 | actually used a lot.
So let's take a look at how this works.
| | 03:28 | So I wanted to clear a character array,
s1 left bracket right bracket = "string", and that creates a
| | 03:35 | character array with seven
elements, the six letters and a null.
| | 03:41 | And I am going to create a character pointer
and assign it to the beginning of the string.
| | 03:46 | Now I am going to print this out.
| | 03:48 | Do reference the pointer so that we can
see that it's actually pointing at the
| | 03:54 | first letter in the array so that is letter s.
| | 03:56 | So we'll save that and run
it, and it says value is s.
| | 04:00 | So again what we have here is
we have an array of characters.
| | 04:04 | The first element is an s,
the second element is a t,
| | 04:07 | the third element is an r and so on and
a character pointer that's initialized
| | 04:11 | to the beginning of the array.
| | 04:13 | And here that *c that dereferences the
pointer, and it gives us the value that's
| | 04:19 | being pointed out which is a character c.
| | 04:22 | Now the beauty of this is that because
pointers are strongly typed in C, when I
| | 04:27 | go and increment that, and I'll just
do a postfix increment first, and we'll
| | 04:33 | make a few copies of that, it
will print the s, the t, and the r.
| | 04:38 | And so we'll save that, and we'll
run it, that's the s, the t, and the r.
| | 04:42 | So what we are doing here is we are incrementing
the pointer and then dereferencing it.
| | 04:45 | So that seems really obvious, and
it seems really straightforward.
| | 04:49 | Here is where it gets interesting.
| | 04:50 | If instead of a character array I make
this an integer array, and we'll call
| | 04:56 | this i1, and we'll initialize it to 1,
2, 3, 4 and 5, and then we'll make an
| | 05:04 | integer pointer, and we'll initialize
that to the beginning of the integer array
| | 05:10 | and then these are going
to dereference integers.
| | 05:13 | So we use %d and ip for the integer pointer,
and we'll do three of them just like that.
| | 05:20 | So now what we have here is we have an
integer array with five elements and they
| | 05:24 | have integer values in them, 1, 2, 3, 4 and 5.
| | 05:27 | We have an integer pointer ip which is
initialized to point at the beginning
| | 05:32 | of the integer array.
| | 05:33 | So it's pointing at that first element
which is the one, and we are incrementing
| | 05:38 | that pointer and
printing out each of the values.
| | 05:42 | Now here's the interesting
thing, an integer is four bytes.
| | 05:46 | When we were doing this with characters
each time we incremented the pointer, it
| | 05:49 | would increment by one byte in the
array to the next element to the array.
| | 05:54 | Here these elements and the array are
actually farther apart, they're four bytes
| | 05:58 | apart rather than one byte apart.
| | 06:00 | But the beauty is because the pointer
is strongly typed it knows that when you
| | 06:05 | use the increment operator it's going
to increment not by one byte, but by the
| | 06:09 | size of the object that it's
pointing to, in this case, four bytes.
| | 06:13 | So we will actually get 1, 2, and 3 just
like we would expect, but the important
| | 06:18 | thing to remember is that it's
actually incrementing differently, it's
| | 06:21 | incrementing by the size of the object
that it points to, and it knows that size
| | 06:25 | because the pointer itself is
typed to point it an integer.
| | 06:29 | So I am going to run this, and
we'll see what we get the result that we
| | 06:33 | expect, 1, 2, and 3.
| | 06:34 | And just like with the integers we can
use postfix or prefix increments and get
| | 06:39 | exactly the same result.
| | 06:41 | Here it has 2, 3, and 4 because it's
incrementing before it's taking the value.
| | 06:46 | So this usage is actually very common.
You'll commonly see something like this.
| | 06:55 | And I am going to terminate this with a 0
because that's the common pattern for that.
| | 07:03 | So you will commonly see patterns
like this where we have initialized a
| | 07:06 | pointer to point at the beginning of
the array, and we are going to loop
| | 07:10 | through while there is still a value
being pointed at, and we are going to
| | 07:14 | increment that pointer.
| | 07:15 | And you can use this for any type of an
object as long as you have a terminator
| | 07:19 | that you can test for.
| | 07:20 | In this case, it will
print out 1, 2, 3, 4 and 5.
| | 07:24 | And because these pointers are
strongly typed if you're able to just use
| | 07:28 | the increment operator like this and let
the pointer worry about how far to increment.
| | 07:32 | So unary increment and decrement
operators are very useful and very common.
| | 07:38 | Keep in mind that the prefix version
increments before returning the value and
| | 07:42 | the postfix version
increments after returning the value.
| | 07:45 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using comparison (relational) operators| 00:01 | The comparison operators are used to
compare for equality or from relative value.
| | 00:05 | Let's open a working copy of working.
cpp, copy that and paste it into our
| | 00:10 | Working project here in
Eclipse and open it up in the editor.
| | 00:14 | We'll start out by declaring a couple
variables int x and int y, and we will
| | 00:22 | just say if x>y, and we'll cout x greater
than y and else x is not greater than y.
| | 00:43 | So if I save that and run it we will
get x is not greater than y, and we can
| | 00:48 | delete this line down there, and
that's because x is 5 and y is 6.
| | 00:54 | So if I make x equals to 7 then we save it
and run it, now we get x is greater than y.
| | 01:01 | Also, test for equality.
| | 01:03 | So if we can say if x == y, and that's
a double equal sign, and say x equal to
| | 01:15 | y and then here we can make this an else/if.
| | 01:20 | And now if neither those is true
then we know that x is less than y, and
| | 01:26 | save that and run it.
| | 01:30 | And we get x is greater than y, and if
we make them the same, save that and run
| | 01:36 | it, we get x equal to y.
We can also test for inequality.
| | 01:41 | So we can say x is not equal to y and
test for that, and we can test for that
| | 01:48 | separately when we still want to know
if one is greater than the other, and
| | 01:52 | we'll make y =9.x not
equal to y, x is less than y.
| | 01:56 | And if we make X = 9, then
we just get x equal to y.
| | 02:01 | There's also greater than or equal
to which looks like this, and there's
| | 02:06 | less than or equal to which looks like that .
I'm just going to save that.
| | 02:11 | So these are the comparison operators.
| | 02:13 | They work of course on
integers as we see, floating point.
| | 02:16 | They work on any scale or type and they
will even work of objects by overloading
| | 02:21 | the operators, and we will talk about
operator overloading later in the course.
| | 02:25 | So the comparison operators are used to
compare for relative value or for equality.
| | 02:29 | They are simple and effective
and they work on any scale or type.
| | 02:33 | For a more complex type that may be
overloaded and overloading operators is
| | 02:37 | covered later in this course.
| | 02:39 | So let's go ahead and delete working.cpp, press the
Delete key, and Clean to get ready for the next lesson.
| | Collapse this transcript |
| Using logical operators| 00:00 | The logical operators are distinct from
the comparison operators or the bitwise
| | 00:04 | operators, these are for
logically combining conditions.
| | 00:07 | Let's take a look at an example, we'll
make a working copy of working.cpp out
| | 00:12 | of the Chap06 folder of the ExerciseFiles and
paste it into our Working project and open it up.
| | 00:18 | First of all, to understand what a
logical condition is if I say if(true), I
| | 00:23 | have a logical condition that is
true, and I'll just say puts("true");
| | 00:28 | and else puts("false");, and if I save
this and run it, it'll say true, and if
| | 00:35 | change that true to
false then it will say false.
| | 00:39 | So true and false are keywords in C++
that represent a logical state.
| | 00:45 | In regular C you can use 1 and 0.
| | 00:47 | So if I say if(1) that will be true,
and if I say if(0), that will be false.
| | 00:55 | And you can have it be the result of a
comparison or any kind of an operation
| | 01:00 | really that returns a 0 or a not 0 value.
| | 01:03 | So if I say int x = 7, and int y = 9,
and then I can say if(x == y), and we
| | 01:13 | would expect that to be false. All right!
So that's what a logical condition is.
| | 01:18 | It's really just the result of an
expression that is either 0 or not 0.
| | 01:23 | And for most intents and purposes it's
the result of comparisons or things like
| | 01:28 | that, that are either going to be
true or they're going to be false.
| | 01:31 | So for our purposes for testing these logical
operators we're going to use true and false.
| | 01:35 | Again this is a C++
idiom and does not work in C.
| | 01:38 | And so if I say, if(true && true),
since both of those things are true then the
| | 01:45 | logical & of them is also true.
| | 01:47 | So I can run that, and I get it true.
| | 01:49 | And if I say if(true || true)
and so OR is two vertical bar.
| | 01:54 | One of them has to be true in order for
this to be true, and so if I run that--
| | 01:59 | I didn't save it, I'll go ahead and
say Save--then it comes out as true.
| | 02:03 | I am going to delete these lines because
they are giving me warnings, there we go.
| | 02:07 | Now if I say (false || false) then
because both of these are false, we'll get a
| | 02:14 | false as a result, it says false.
| | 02:16 | If I say if(false || true) because one
of them is true we'll get a true, save
| | 02:22 | that and run it, and we get true.
| | 02:24 | And if I say (false && false), that's
two ampersands for AND, then that will
| | 02:31 | be false because in order for & to be true both
sides of it have to be true, so we get false.
| | 02:36 | Finally, we have the logical NOT operator,
which is simply an Exclamation Point.
| | 02:41 | So if I say (!true) that's
going to come out to be false.
| | 02:45 | So I'll save that and run it, and it's false.
| | 02:47 | If I say (!false) then it returns the
inverse of that, which is true, and I'll
| | 02:52 | save that and run it, and I get a true.
| | 02:55 | So logical operators are NOT, which is
a single Exclamation Point, and which is
| | 02:59 | a double ampersand or OR
which is a double vertical bar.
| | 03:05 | The logical operators are simple and
straightforward, they operate on logical
| | 03:08 | conditions or they maybe
overloaded for working with classes.
| | 03:12 | Operator overloading is
covered later in this course.
| | 03:16 | So let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Exploring bitwise operators| 00:00 | C and C++ provide Bitwise, Boolean,
Arithmetic operators for use with integers.
| | 00:06 | Let's start with a working copy of our
working.cpp program, and we'll paste this
| | 00:12 | into the Working project, and
we'll create a couple of integers.
| | 00:16 | These are unsigned integers
x = 5, unsigned int y = 10.
| | 00:24 | And I'm going to use printf
so I can format this in hex.
| | 00:27 | So %08x, and I'm going to do three of
those and a new line, and that will be x
| | 00:36 | and y and our operation, in this case
we're going to go ahead and do x & y and a
| | 00:41 | single ampersand is the bitwise and.
| | 00:45 | And so what that'll do is it will go
through the integer x and the integer y and
| | 00:50 | bit by bit it'll compare the
corresponding bit in the corresponding variable.
| | 00:54 | And for the and operation if they're both
set, then it'll set the bit in the result.
| | 01:01 | Now, I happen to know that 5 is 0101 in
binary and 10 is 1010 and so the and of
| | 01:11 | these two will be 0, because
they don't have any common bits set.
| | 01:15 | So I'll save this, and I'll run
it, and we see that the and is 0.
| | 01:20 | So we have 5, we have a, which is hex
for 10, and we have 0 as the result.
| | 01:26 | On the other hand if we say or and that'll
be true if the corresponding bits are set.
| | 01:31 | And or is a single vertical bar, and
this is a bitwise or so I'll save this and
| | 01:36 | run it, and we see we get an
f which is all the bits set.
| | 01:40 | There is also an exclusive or
exclusive or is the caret symbol, and this will
| | 01:47 | set the result if the
two operands are different.
| | 01:49 | In other words, if a particular bit is
set on x and clear on y, it'll be true.
| | 01:54 | And if a particular bit is clear
on x and set on y, it'll be true.
| | 01:58 | So we'll save that and run it,
and we see we get f again.
| | 02:02 | There is also a bitwise not.
| | 02:06 | And so that one look like this is a tilde,
and that will simply flip all of the bits.
| | 02:13 | So any bit that is set in x will be
clearing the result and any bit that is
| | 02:18 | cleared in x will be set in the result.
And so when we run this, we'll see we get ffffa.
| | 02:24 | There are also shift
operators for shifting left.
| | 02:27 | So this will take any bits that are set,
and it will shift them left by four
| | 02:31 | bits, and it will leave the bits clear
to the right of all of that, and so we'll
| | 02:36 | run that, and we see the result is 50.
| | 02:41 | And we can do the same to the right,
and I'm just going to change this to make
| | 02:45 | it 0x50, and when we shift
to the right it'll be 05.
| | 02:52 | So in their natural state these
bitwise operators only work on integers, but
| | 02:57 | they can be overloaded to
work on different types.
| | 03:01 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with compound assignment operators| 00:00 | As a convenience C and C++ support
compound assignment operators that allow you
| | 00:06 | to combine an assignment
with an arithmetic operation.
| | 00:09 | There are 10 of these operators
they are for addition, subtraction,
| | 00:13 | multiplication, division,
modulus, bitwise shift left,
| | 00:16 | bitwise was shift right
bitwise and bitwise or and
| | 00:21 | bitwise exclusive or.
Let's take a look at how these work.
| | 00:24 | Let's take a working copy of our working.cpp
and paste that into our Working project.
| | 00:32 | I'll double-click on that and open it up.
| | 00:34 | So I'm going to come in here and
declare a couple of integers int x and int y.
| | 00:40 | And if I give them
values I'll say x = 5 and y = 10.
| | 00:46 | And now if I wanted to add x to y
and put the result in x I could say
| | 00:51 | something like x = x + y.
| | 00:54 | And then I can print that out, I'll just
use a printf for this, x is %d, and now
| | 01:01 | our result should be something like 15.
| | 01:04 | So I'll save that and run
it, and it says x is 15.
| | 01:08 | The equivalent way to do this with a
compound assignment operator is to say x +=
| | 01:14 | y, it looks much simpler and cleaner,
and it gives us the same result, save it
| | 01:18 | and run it and x is still 15.
| | 01:21 | There's one important distinction though,
in this other expression I'll just go
| | 01:25 | ahead and I will put them both here
as you can see them both really clearly.
| | 01:29 | In x = x + y the x is actually
evaluated twice and in x += y, x is
| | 01:37 | only evaluated once.
| | 01:39 | So here's an illustration of
how this can have the impact.
| | 01:42 | I'm going to create a
very contrived function here.
| | 01:44 | It's going to return an integer
reference, remember references were covered
| | 01:48 | in our last chapter.
And I am going to pass it an integer reference.
| | 01:53 | And I am just going to printf inside
of it actually we can use a puts for
| | 01:58 | this, puts this is f.
| | 02:01 | And I'm just going to return an
incremented i, so it'll increment it first
| | 02:06 | and then return it.
| | 02:08 | So whatever you pass this function it
gets incremented and returned, but what gets
| | 02:12 | incremented and returned is actually a
reference to the original variables.
| | 02:16 | The original variable itself will be
what's return all right. All right!
| | 02:20 | And so down here I am just going to
delete these for now, and I will do
| | 02:25 | that, that for now.
And down here I say f(x) += 1.
| | 02:32 | What its doing is it's taking that x,
and it's incrementing it out here and also
| | 02:37 | incrementing it inside of the function.
So result should be self 7.
| | 02:40 | All right we'll save that
and run it and the result is 7.
| | 02:45 | And actually x itself is also 7 at this point.
| | 02:48 | So I'll just make a working copy of this,
and I'll say x is, and I'll just put x there.
| | 02:54 | And this one here is actually result it's not x.
| | 02:57 | All right, and so if I save that
and run it we see that x is now 7.
| | 03:02 | And this is f that means we've
evaluated that function once.
| | 03:06 | Now if I were to do this instead and
say f(x) = f(x) + 1, now this function is
| | 03:14 | getting evaluated twice.
| | 03:15 | Right? I'll save that and run
it, result is 8 and x is 8.
| | 03:20 | So that's to say that this x = x + y
is not the same as x += y, ostensibly
| | 03:29 | they do the same thing.
| | 03:31 | But one of them evaluates x twice
and one of them evaluate x only once.
| | 03:35 | This can become significant in cases
where you are using objects and what is
| | 03:39 | going on inside of those
objects may not be terribly apparent.
| | 03:43 | And you need to know that when you're
using a compound operator you're only
| | 03:48 | evaluating that left-hand side once,
whereas when you're using a separate
| | 03:52 | operators for the mathematical operation
and the assignment that you're actually
| | 03:56 | evaluating that left-hand side twice.
| | 03:59 | So the compound assignment operators
as we know they're available for the 10
| | 04:02 | operators plus minus
multiplication division modulus shift left shift
| | 04:08 | right and 3 bitwise logical
operators and or and exclusive or.
| | 04:13 | In most cases using the compound
operator will be an advantage and the side
| | 04:17 | effects will reduced.
You just need to be aware of how it works.
| | 04:20 | These compound assignment operators
are there for convenience, feel free to
| | 04:23 | use them whenever you would use the
equivalent expression just be aware of the distinction.
| | 04:28 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using the array subscript operator| 00:00 | The array subscript operator is
really very simple, let's take a look.
| | 00:04 | Make a working copy of working.c and
paste it into our Working project and open
| | 00:10 | it up in the editor here.
| | 00:12 | I'm going to start by defining an
array, and we'll make an array of ints,
| | 00:16 | because that seems pretty easy to do,
and I'll just put some values in here, and
| | 00:20 | then I'm just going to
replace this with a printf here.
| | 00:24 | We'll go ahead and we'll put in, say,
ia sub 0, and so that's the subscript
| | 00:29 | operator right there.
| | 00:30 | The square brackets and the digit
inside is the subscript and so, like so many
| | 00:37 | things in C, it's normally written
this way with those spaces, but you could
| | 00:40 | put all these spaces around it, and it
would still do exactly what it supposed to do.
| | 00:45 | So I'll just save this and run it, and
you can see, it says value is 1, which is
| | 00:49 | the first element to the array and
arrays are always zero-based and so the
| | 00:53 | subscript operator will always start at
zero for the first element of the array.
| | 00:58 | Of course, you can also use an
integer or any integer type, you could use
| | 01:02 | anything character, short, integer,
long, I am going to just use an integer
| | 01:07 | because that's traditional, and I'll
just give it a value of 3, and if we use
| | 01:11 | that integer to subscript the array, C
will get element number 3 which is the
| | 01:15 | fourth element which will be
number 4, save that and run it.
| | 01:19 | Of course, if we were to make this a 5,
and I'm not going to run that, I have
| | 01:24 | no idea what will happen, and I hate
surprises, because that is what's called undefined.
| | 01:28 | There are five elements in the array
and 5 would access the sixth element and
| | 01:32 | so it would somewhere out here in
nether-nether land, and we don't know what
| | 01:37 | that would be, it could crash our
program, it could create a security hole, it
| | 01:40 | could allow people to come in and
hijack our computer and send out bazillion
| | 01:44 | pieces of spam with it.
| | 01:45 | So we're not going to do that, but just
know that subscripting past the end of
| | 01:49 | an array is what's called undefined behavior.
| | 01:51 | Now the subscript operator
also works on STL containers.
| | 01:56 | We're going to cover STL containers in
a later chapter when we talk about the
| | 01:59 | standard template library, but I just
want to show you this right now because we
| | 02:03 | actually commonly use an STL container,
that is the string type in C++, people
| | 02:08 | think of it as a type, it's really just
an STL container, and it's part of the
| | 02:12 | Standard Template Library.
| | 02:13 | So I'd say string s = and just type the
word string, and I come in here, and I'm
| | 02:20 | going to change this to a character,
because this is now going to be from s, and
| | 02:25 | if I say s sub 5, now we have something
there, that's the sixth element that'll
| | 02:29 | the letter g, and I've got my integer 5,
and I'm subscripting like this, and I
| | 02:34 | just run it, and I actually get a letter g.
| | 02:37 | So, you can subscript STL
containers using the subscript operator even
| | 02:42 | though they're not arrays.
| | 02:43 | Why does that work, because the STL
containers have overloaded the subscript
| | 02:47 | operator and so you can do this too as
you create your own objects, and we'll
| | 02:51 | get into containers in a later chapter,
and we will cover operator overloads
| | 02:56 | in a later chapter, but just know
that that's what's happening when you see
| | 03:00 | that common pattern.
| | 03:01 | So the subscript operator it used for
indexing arrays and containers, and it's
| | 03:06 | simple to use, you just need to
remember that it's zero-based.
| | 03:09 | So let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using pointers, members, and indirection operators| 00:00 | C and C++ offer a number of operators
for working with pointers and members
| | 00:04 | of compound data structures, and I
group these together because they're so
| | 00:08 | often used together.
| | 00:09 | Let's make a working copy of deref.cpp,
and we'll paste that into our Working
| | 00:15 | project and open it up in the editor here.
| | 00:17 | Here we have a structure called S with
a capital S, and it's got three
| | 00:22 | members, and we've declared an
initialized variable called lowercase s, and
| | 00:27 | we've initialized it with 1, 2
and 3 and members a, b and c.
| | 00:31 | And we're printing it out, if we go
ahead and run that, we see s has members a,
| | 00:36 | b and c as 1, 2 and 3.
| | 00:39 | So this period in between the s and the
a, and the s and the b and the s and c
| | 00:45 | is actually a member operator.
| | 00:47 | And it's for accessing the
members of a structure or a class.
| | 00:52 | And C++ structures and classes
are almost exactly the same thing.
| | 00:56 | We'll get into C++ structures
and classes in a later chapter.
| | 01:00 | But for purposes here we want to know
how to use this operator to access members.
| | 01:04 | And so it is an operator, in fact you
can put spaces around it just like that
| | 01:08 | just like any operator, and it still does
exactly what you expect it to do just save and run.
| | 01:15 | And so that's easy, that's how you
access the members of a structure.
| | 01:20 | Now suppose we have a pointer to this
structure instead and so we say struct
| | 01:24 | capital S* which is to declare pointer,
and we'll call our pointer sp, and we'll
| | 01:31 | assign it to the address of s, right.
| | 01:35 | So this ampersand here is the address
of operator, and it takes the address of
| | 01:40 | that variable there, that s.
| | 01:42 | And it allows that to be assigned
and so here it's being assigned to this
| | 01:46 | pointer of the same type so that works great.
| | 01:48 | Now if I want to access those numbers
through pointer I can say sp and use the
| | 01:54 | pointer access operator and say a, and
I'll just copy and paste that for the
| | 01:59 | other two, it starts getting a little
bit long, so we'll go ahead and we'll put
| | 02:05 | it on a separate line here.
| | 02:06 | And that will be c, and that will be
b, and now we're dereferencing that
| | 02:12 | through the pointer.
| | 02:13 | So we are dereferencing the pointer and
getting to the members all in one operator.
| | 02:17 | And so this dash greater than
operator, that's the operator there, so you
| | 02:21 | can't have any spaces between those or
to look like a minus and greater than
| | 02:25 | and the compiler doesn't know what do you mean,
you can see right away it's got the syntax error.
| | 02:30 | But if I take that space out in between
those two characters, now we have this
| | 02:34 | pointer dereferencing operator, and
that dereferences and gets to the member
| | 02:38 | all in one operator.
| | 02:39 | So I'll save that and run it, and we
see we get exactly the same result.
| | 02:44 | So if I make a copy of this and
paste it in here, and we can use s.
| | 02:51 | for each of these, so we can get at the
members of the structure directly, and
| | 02:57 | that's what the membership operator or
we can get at them indirectly with the
| | 03:01 | member dereference operator.
| | 03:04 | Save that and run that you see we get
the same result with both of those lines.
| | 03:08 | So even see with no object-oriented
extensions, it's so very common to
| | 03:12 | dereference pointers to structures.
| | 03:13 | In C++, structures and classes
use the same syntax and are actually
| | 03:18 | interchangeable, so these
operators are very common there too.
| | 03:22 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Exploring the function call operator| 00:00 | The function call operator is
used to make function calls.
| | 00:03 | It can be used with functions,
pointers and even with objects.
| | 00:07 | Let's make a Working copy of funcop.cpp,
and we'll paste that into our Working
| | 00:12 | project and double-click on
it to open it up in the editor.
| | 00:16 | So here we have a simple little function.
| | 00:18 | It takes an integer, and it returns an
integer and so we've declared an integer
| | 00:22 | here, and we're assigning to that
integer from the function passing it a 47 and
| | 00:27 | of course it will return a 47.
| | 00:29 | So we'll go ahead and run that, and we
see it says this is f, when it's running
| | 00:34 | the function itself, and it says i is 47.
| | 00:37 | So that's what we expect to have happen,
and this is the function call operator.
| | 00:43 | It's the parentheses, and you can put
inside of the parentheses any arguments
| | 00:46 | that you have to send to the function.
| | 00:48 | Now if we were to declare a pointer to
this function, show you a lot of what
| | 00:54 | goes on here with that operator, so the
function returns an int, and we need to
| | 00:58 | know the exact function signature,
because it will not work if we don't get that
| | 01:02 | straight, and I'll show you what happens.
| | 01:04 | So a pointer to a function looks like
that, and I can assign to it, I can say
| | 01:10 | pFunc = &f and remember the ampersand
operator is the address of, so it's taking
| | 01:16 | the address of our function called f.
| | 01:18 | And so a function is effectively a
type, and I have this variable of type
| | 01:23 | function which is f, and it
refers to this function here.
| | 01:27 | I am simply taking the address of it,
and I'm assigning it to this pointer.
| | 01:30 | Now the syntax for the pointer to a
function is admittedly a little bit obtuse,
| | 01:36 | but it's not that hard to remember.
| | 01:38 | You have the function pointer itself
inside the parentheses, and that's just
| | 01:41 | because if you just say *pFunc, it
doesn't tell the compiler that this is a
| | 01:47 | function type and so we need a
pointer to the function type.
| | 01:50 | So, we put it in the parentheses, and
then we have whatever parameters reported
| | 01:54 | that function signature and remember
that the function type itself includes what
| | 01:58 | it returns, and it includes the
function signature what goes inside of the
| | 02:02 | parentheses so that's all
part of the function signature.
| | 02:05 | So here we have a pointer to a function that
returns an int and takes an int as a parameter.
| | 02:10 | And I take that pointer, and I
assign the address of the function to it,
| | 02:13 | and then I call it.
| | 02:15 | And so, I call it like this, and that
will call the function through the pointer
| | 02:20 | rather than directly.
| | 02:21 | So we'll save this, and we'll run it, and we
see that we get the exactly the same result.
| | 02:26 | Now obviously we can do the
assignment on the same line.
| | 02:30 | So we do the initialization there, on
the same line that we declare it, and that
| | 02:34 | still works just fine.
| | 02:35 | I'm going to save that and run it, and
you'll notice that if I take this int out
| | 02:40 | of the parentheses, I now have a
different type and so it's not compatible, and
| | 02:45 | that assignment will not work.
| | 02:47 | So I'll save that and try to compile
it and run it, and you see that I get
| | 02:51 | an error right here.
| | 02:53 | Invalid conversion from, and
there you've got the two types.
| | 02:56 | The function call operator is commonly
used for calling a function, but as you
| | 03:00 | can see, it's actually very
powerful and flexible in its own.
| | 03:03 | We'll cover function objects and
overloading function operators in more detail
| | 03:07 | later on in the Classes and Objects chapter.
| | 03:09 | Let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with the ternary conditional operator| 00:00 | The ternary conditional operator is a
great name for a simple shortcut for
| | 00:05 | choosing a value based on the condition.
| | 00:07 | Let's make a working copy of working.cpp
and paste this into our Working project
| | 00:13 | and open up it on up.
| | 00:14 | I'll go ahead here and declare a couple
of variables int i=5 and int j=47, and
| | 00:21 | then I am just going to change this to
printf ("is the condition true? %s",).
| | 00:29 | So what I need here is a c-string.
| | 00:31 | I'm going to put this on a line by itself, and
I'm going to say, if i > j ? "yes" : "no");.
| | 00:42 | So that is the ternary
conditional operator right there.
| | 00:45 | See it's ternary because it has a left-
hand side, it has a right-hand side, and
| | 00:50 | it's got a middle side.
| | 00:51 | So if the condition to the left of
the question mark is true then the
| | 00:56 | operator will return the first operand,
and if it is not true then it will
| | 01:01 | return the second operand.
So if I save this and run is the condition true?
| | 01:06 | No, because i is not
greater than j. j is 47, i is 5.
| | 01:11 | If I say it if i < j then the conditional
return save it and run it, and it's true.
| | 01:18 | So it's really very simple.
| | 01:20 | It's kind of looks a little bit obtuse
the first time you look at it, but it's
| | 01:25 | very simple, and it's extremely
convenient, because the alternative is to do a
| | 01:28 | complicated if/else, and this is a
simple expression that just returns either
| | 01:33 | one or the other value. Very convenient.
| | 01:35 | So this can be really handy in cases
where you just need to select a scalar
| | 01:40 | value, and you don't need the
complexity of a block oriented if/else construct.
| | 01:44 | This operator cannot be overloaded.
| | 01:46 | The ternary conditional operator is a
common shortcut for testing a simple
| | 01:50 | condition with a simple scale result.
| | 01:52 | So let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Determining the size of a type with sizeof| 00:00 | The sizeof operator is used to
determine the size of an object.
| | 00:04 | Let's take a copy of working.cpp
and paste it into a Working project.
| | 00:09 | Double-click on that to open it up, and
I'm going ahead and declare an integer,
| | 00:15 | and I'm just going to take
the size of that integer.
| | 00:18 | So we will use printf for this, and we
are going to use the sizeof operator.
| | 00:23 | Sizeof is as an operator, and it
seems a little strange sometimes that it
| | 00:26 | would be an operator, because it's a
word, and it's not a symbol, but still
| | 00:30 | actually an operator.
| | 00:31 | Now the size of operator returns a type
called size T and If I go ahead and run
| | 00:36 | this just like this.
| | 00:38 | I am going to save this and run it, we
will get a warning about a conversion
| | 00:42 | from long unsigned int and to int.
| | 00:45 | And that's because size T in this
implementations is a long unsigned int.
| | 00:49 | It can be different in
implementations, and it's actually spelled size T.
| | 00:54 | And I can put it here as the argument
to sizeof, and because it's a type it has
| | 00:59 | to go in parentheses.
| | 01:00 | I can say size t like that, and I'm
just going to cast this to in int, and that
| | 01:05 | way the cast is explicit, and we
won't get this warning anymore.
| | 01:08 | So I'll save that and run
it, and we see size is 8.
| | 01:11 | So indeed it is a long unsigned int.
| | 01:14 | So I can say size of int, and I'll
get the result of that, and that's 4.
| | 01:20 | So the number that size T returns
is in bytes, and it's not in bits.
| | 01:24 | So 4 bytes for size for the size of int,
8 bytes for a Long or for a size T.
| | 01:29 | The operand here in the case of a
variable I can just say size of i without the
| | 01:35 | parentheses, and that works fine.
| | 01:37 | Save that and run it.
| | 01:39 | But if I'm taking the size of a type
that it needs to be effectively cast.
| | 01:44 | So we have to put that inside a parentheses.
So I save that and run that, and that works.
| | 01:48 | Of course, you can use it to take
the size of other things if I declare
| | 01:52 | struct, and I put a few things in it,
a couple of ints, couple of chars, a
| | 02:01 | couple of long ints, and then inside of here I
can say size of struct S like that, a capital S.
| | 02:08 | I am going to delete that int,
because I am not using it anymore.
| | 02:12 | Save that and run it, and we see the
size is 32 bytes, and that's how much
| | 02:16 | storage space it takes place
for all of those different types.
| | 02:19 | And of course, if I were to declare a
variable of struck S, then I could put
| | 02:24 | that in here, and I don't need the parentheses.
| | 02:26 | I tend to use them anyway, because it
just seems simpler to not have to remember
| | 02:30 | when I need them, and when I don't,
and it doesn't have anything to use them.
| | 02:34 | So I save that and run it,
and we get the same result.
| | 02:38 | The size of operator can be useful
whenever you need to find out how much memory
| | 02:42 | is occupied by an object.
| | 02:43 | It is commonly used for determining
the amount of storage to allocate.
| | 02:47 | So let's go ahead and delete our Working copy
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Determining the type of an object with typeid| 00:00 | The typeid operator is only available in
C++ it returns a type info object which
| | 00:06 | is defined in the typeinfo header.
Let's take a look at how this works.
| | 00:10 | Make a working copy of typeid.cpp and
paste it into our Working project and
| | 00:15 | open it up in the editor here I'm
going to just maximize this, so you can the
| | 00:19 | see the whole thing.
| | 00:20 | And you notice I have also included the
type info header, its really only needed
| | 00:24 | if you're using the members of the
objects that typeid returns, but we're going
| | 00:28 | to do that here so we will take a look at that.
| | 00:31 | You notice I have got a couple of
structs define they don't have anything in
| | 00:35 | them, but they are still considered
types and here I'm testing to see if the
| | 00:39 | type of the variable a1 which is a
struct A is the same as type of the struct A
| | 00:45 | itself and so I should get either
same or different in the result.
| | 00:48 | Let's go ahead and save this and run it.
| | 00:51 | You notice I get a few little warnings here for
the variables I'm not using, and that's fine.
| | 00:57 | And you see it says same.
| | 00:58 | So the typeid of a1 which is this variable
here is the same as the typeid of the structure.
| | 01:05 | So this is really useful for finding
out what type something is if it's this
| | 01:09 | type or if it's that types.
| | 01:10 | So if I checked to see if it's type of struck B,
we can run that, and you see it is different.
| | 01:16 | I can check to see if it's the
same type as a2, which it is.
| | 01:20 | So we'll save that and run it and see
that it's the same, and I can check it
| | 01:24 | against one of Bs, I'll check it
against b2, save that and run it.
| | 01:29 | And we see that one is different.
| | 01:32 | So this is very useful and really easy
to do, so if I really need to find out
| | 01:37 | what type something is now I know how to do it.
| | 01:40 | There's one other use for this, and I find
it much less useful, that I'll show to anyone.
| | 01:44 | So I'm using the name function
member of the object that is returned by
| | 01:50 | typeid, and this is just a shortcut
for doing that without creating an extraneous variable.
| | 01:55 | And so I'll save that and run it, and
you see that it says 1a now my variable
| | 02:01 | is called a1 and its type is struck A
and so interestingly this says that the
| | 02:08 | type name is 1A.
| | 02:11 | So internally somewhere in the compiler
that's the way it's keeping track of it.
| | 02:15 | Different implementations will print out
different things for this, so I find it
| | 02:19 | less than entirely useful.
| | 02:21 | If I take the type of say an int, save
that and run it, you see I get a letter
| | 02:28 | I, and if I say take the
typeid of struct B the save that.
| | 02:35 | And if you get this launch working
you can always just press always run the
| | 02:39 | background if like I am just going to
put the run on the background button.
| | 02:43 | And I get 1B so that's kind of what I'd expect.
| | 02:46 | Let's take one more, let's say the
typeid of the string object rather the string
| | 02:51 | class and save that and run it,
and I see a capital and a lower case.
| | 02:58 | And so we see that what we get out of here that's
not going to be consistent across implementations.
| | 03:02 | And really we can find whatever we need
to find out by comparing it to the types
| | 03:06 | that we think something might be.
| | 03:08 | So the typeid operator is only
available in C++, and it is not available in C,
| | 03:13 | it returns a type info object, and you
can use the name function member of that
| | 03:17 | if you like, and that is
defined in the typeinfo header.
| | 03:22 | So now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using the cast operator| 00:00 | The cast operator is used to convert an
object of one type to another compatible type.
| | 00:06 | Let's make a working copy of our working.cpp
and paste it here into our Working
| | 00:12 | project and double-click on it to open it up.
| | 00:15 | So I am going to go ahead and create
a variable of type int, and I'm going
| | 00:19 | assign to that size of int.
| | 00:23 | I know the sizeof returns a size T
value, which on this machine with this
| | 00:29 | compiler is an unsigned long int.
| | 00:32 | I am going to go ahead and printf out "
value is %d\n" i, and we will save that
| | 00:40 | and run it and see what happens.
Now that runs just fine, and it says value is 4.
| | 00:45 | Now if instead here I just take this, and I
put it there, interesting things happen.
| | 00:52 | Save this and run it.
This launching thing comes up.
| | 00:57 | You can just hit the Always
run in background if you like.
| | 01:00 | I'm just going to hit the Run in background.
| | 01:02 | And it says values for, and I get a
little warning here, and you notice the
| | 01:06 | warning says format "%d" expects
argument of type "int", but argument 2 has
| | 01:09 | type long unsigned int".
| | 01:11 | So what we have here is a slight
incompatibility, and it's really just a
| | 01:15 | warning, and it's not a big deal
along int converts just fine to an int.
| | 01:18 | You lose some information, but sizeof
isn't really returning any numbers that
| | 01:22 | are big enough for that to matter.
| | 01:25 | So the way that I get around this is I
tell the compiler use this as if it's an int.
| | 01:30 | Go ahead and make sure you convert
this to an int, and I do that by putting
| | 01:36 | the word int in parentheses left of the
thing that I wanted to force a conversion on.
| | 01:40 | Just like that.
| | 01:41 | I save that, and I run it,
and it solves the problem.
| | 01:44 | My warning goes away.
| | 01:45 | So this is called a cast, and this is
the traditional C form of cast which is to
| | 01:50 | put the type in parentheses to the left
of the object that you want to convert,
| | 01:55 | and that's the formula I used them most often.
| | 01:58 | There's also another version, that is C++
only, and that is to take the type and
| | 02:03 | put the value in the parentheses
instead, and that looks like that, and I can
| | 02:07 | save that and run it, and
it works exactly the same.
| | 02:10 | So this form looks like I'm declaring a
variable of a class is what it looks like.
| | 02:17 | For some people that might
be a more familiar paradigm.
| | 02:20 | I'm an old C programmer from
way back, so I like this one.
| | 02:23 | Really, it's just a matter of style.
| | 02:25 | The other thing I like about using
the C form is that it's compatible.
| | 02:29 | I can use it both in C, and I can
use in C++ and the function form is
| | 02:34 | only usable in C++.
| | 02:37 | The cast operator is used to force a type
conversion between two compatible types.
| | 02:42 | There are two forms, the traditional C
form that puts the type in parentheses or
| | 02:46 | the newer C++ function form
which puts the value in parenthesis.
| | 02:51 | You may use whichever form works for you.
| | 02:54 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with the new and delete operators| 00:00 | The new and delete operators are
used to allocate and free memory in C++.
| | 00:06 | Let's make a working copy of new-delete.cpp
and paste it in our Working project
| | 00:12 | and open that up on.
| | 00:14 | I'm going ahead and maximize this so you
can see the whole thing, and let's take
| | 00:17 | a look at how this works.
| | 00:19 | You notice that I am also including C
standard def, and that's because the null
| | 00:23 | constant exists in that header file in C++.
| | 00:26 | In C it's usually kind of declared
everywhere, because it uses it so much.
| | 00:32 | We start out here at the top, we use
the new operator to allocate memory
| | 00:37 | for count integers.
| | 00:39 | So there is int, and there
is count and our count is 100.
| | 00:43 | So this will allocate
space for a hundred integers.
| | 00:45 | The new operator takes as operand a
type and optionally a count in square
| | 00:52 | brackets to tell you how many.
| | 00:53 | So if I were to just say new int like
this, it would allocate space for one
| | 00:57 | integer, and this allocate space for
count integers which is a hundred and the
| | 01:03 | new operator returns a pointer.
| | 01:05 | So in this case I am declaring and
initializing a pointer to int called IP.
| | 01:11 | I'll then check if IP equals null, and
if it does I put out an error message
| | 01:16 | that new failed, and I return a failure code.
| | 01:19 | Otherwise, I step through a count
pointers incrementing the pointers and
| | 01:24 | populate this data structure with
integers, and then I print them out.
| | 01:29 | Then I use Delete to delete the space.
| | 01:32 | It's important for every new that
there be a corresponding delete.
| | 01:36 | If I allocate something with new, and I
do not delete it with Delete I'm going
| | 01:40 | to have a leaky program, and it's
going to crash and have weird problems.
| | 01:44 | So whenever you use new it's
important to also use Delete.
| | 01:47 | So we will go ahead and put this back
and save it and run it, and we see that we
| | 01:52 | have 100 integers printing.
| | 01:55 | Now if I go ahead and make this a
really big number, and I'm going to make this
| | 02:00 | fifteen zeros-- One two three four five, one two three
four five, one two three four five.
| | 02:06 | Let's save that and run it.
I get an exception.
| | 02:09 | It says is malloc size blah, blah, blah failed.
| | 02:12 | Set a breakpoint, terminate after
throwing an instance of bad_alloc.
| | 02:17 | So we got an exception, and we didn't
really get to get to our test here to
| | 02:22 | see if new failed.
| | 02:24 | So there is an option to new called
nothrow which you put in parentheses after
| | 02:31 | the keyword and before the type, and
I'll go ahead and save this and run it, and
| | 02:35 | you'll notice the GCC isn't really obeying here.
| | 02:39 | It still gives me its error message,
but it's not throwing the exception.
| | 02:45 | It still prints out the error message though.
That's not terribly useful.
| | 02:48 | But you notice I do get my new failed,
because I am able to actually test for new failed.
| | 02:53 | So the new operator is used for
allocating space for objects in C++.
| | 02:59 | Every object allocated with the new
operator must be destroyed with Delete,
| | 03:03 | otherwise your program will leak memory.
| | 03:06 | So let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Understanding operator precedence| 00:00 | Operator precedence is the order in which
operators are evaluated in an expression.
| | 00:05 | This expression could have different
results depending on what order it's evaluated in.
| | 00:10 | For example, using parentheses to
bind parts of the expression together if we
| | 00:14 | give precedence to the addition then
the multiplication, we get this result.
| | 00:19 | And if we move the parentheses
around a bit, we get a different result.
| | 00:22 | And if we remove the parentheses
we can get yet a different result.
| | 00:27 | The order of evaluation without any
parentheses is that the division happens
| | 00:31 | first, then the
multiplication, and then the addition.
| | 00:34 | It's as if it were parenthesized like this.
| | 00:37 | The point of understanding operator
precedence is to be aware of the rules.
| | 00:41 | You don't need to memorize the rules,
| | 00:43 | there are plenty of handy reference
tables available, but you do need to know
| | 00:47 | that this is how it works.
| | 00:49 | Ultimately, if you care about the
order of evaluation of an expression it's
| | 00:53 | always best to use the parentheses.
| | 00:56 | So here in your ExerciseFiles there's a PDF
file that is an Operator Precedence table.
| | 01:01 | I am just going to maximize it
up here so that you can see it.
| | 01:05 | I've included a copy of this in the
ExerciseFiles or it's easy to find online.
| | 01:09 | I keep a laminated copy of this
actually by my workstation just for quick
| | 01:13 | and easy reference.
| | 01:15 | So this shows all of the operators
available in both C/C++ with the highest
| | 01:20 | precedence operators at the
top and the lowest at the bottom.
| | 01:23 | So if we have an expression that has
several operators in it, the ones that are
| | 01:28 | closest to the top here will give
evaluated first, and the ones that are closer
| | 01:33 | to the bottom will get evaluated last.
| | 01:36 | Here's a simplified version of
the operator precedence table.
| | 01:39 | Most operators are evaluated left to
right except prefix unary and assignment
| | 01:44 | operators which are evaluated right to left.
| | 01:47 | It's important to understand operator
precedence, but it's not so important to memorize it.
| | 01:52 | Most of the time it's a good idea to use
parentheses to specify the order you
| | 01:56 | want your expressions to be evaluated in,
and it's easy to keep a chart near
| | 02:00 | your workstation for when you need to
read someone else's code who may not have
| | 02:04 | been so considerate as to use parentheses.
| | Collapse this transcript |
| Using operator synonyms| 00:00 | C++ provides a few interesting synonyms for
some of the logical and bitwise operators.
| | 00:06 | Let's take a look at how these work.
| | 00:08 | Let's make a working copy of working.cpp
and paste that into our Working project.
| | 00:14 | Open it up in the editor, and
let's consider this expression here.
| | 00:18 | I am going to declare and
initialize a couple of integers.
| | 00:26 | So, that's fairly simple.
We have two integers, a and b.
| | 00:29 | One of them is false, one of them is true,
and then we test if they're both true
| | 00:34 | with the And operator,
that's the logical And the &&.
| | 00:38 | And if they're true, we'll put a true, and
if they're false, well, I will put a false, very simple.
| | 00:43 | We'll go ahead and delete this line
down here, save it and compile and run, and
| | 00:48 | we see we get the result false.
| | 00:50 | Now, using an operator synonym, I can
take this && for And, and I can make it
| | 00:57 | into the much more human friendly word
and you see even Eclipse knows about
| | 01:02 | it and highlights it.
| | 01:04 | Then I can save this, and I can run it, and we
get exactly the same result. Very slick, right?
| | 01:09 | Now, consider this expression.
| | 01:14 | Look how funny Eclipse gets
when I forget a semicolon.
| | 01:19 | So, if I go ahead and save this and
run it, we get this 32, and this is the
| | 01:25 | bitwise And of and b.
| | 01:28 | There's another handy-dandy synonym,
it's called bitand, and I can put it there,
| | 01:33 | and save this, and run it, and
you see we get the same result.
| | 01:38 | Now, if I were to simply forget to type
this a here and just accidentally type c = bitand b
| | 01:45 | and save it and run it,
look at the error that I get.
| | 01:51 | It says I'm trying an invalid
conversion from an integer pointer to an int.
| | 01:56 | That doesn't seem like what
it is that I'm trying to do.
| | 01:59 | There's a reason for that.
| | 02:00 | The reason for that is that bitand is
not actually a synonym, it's a text alias.
| | 02:05 | If I replace this with the &, you'll
notice that what it is is that I'm trying
| | 02:11 | to assign the address of b to c, and so
bitand is not really a synonym for the
| | 02:18 | bitwise And operator, it's
actually just a text alias.
| | 02:22 | This is very, very confusing,
and the problem gets even worse.
| | 02:26 | If I do something like this, and I save
this and run it, look at that, no error at all.
| | 02:31 | C equals 112, because what this is again,
if I take that bitand out, and I put
| | 02:37 | in an ampersand, we see it's simply a reference.
| | 02:40 | I've declared a reference, a C
reference, and I've assigned it to b, which is
| | 02:44 | perfectly legal, and bitand
makes no sense there whatsoever.
| | 02:48 | So, it's very important to
understand how this works.
| | 02:51 | Officially, these are synonyms for
logical operators, but in reality, they're
| | 02:55 | text aliases just like macro expansion.
| | 02:58 | Frankly, I don't see their value, and I
never use them, and I suggest that you
| | 03:02 | don't use them either.
But if you do choose to use them, be careful.
| | 03:06 | This is a table of the operator
synonyms that are defined in the C++ language.
| | 03:10 | Keep in mind that these synonyms are actually
text aliases, and they can be a bit dangerous.
| | 03:16 | Because it doesn't really add anything
substantive to the language, and it can
| | 03:19 | provide confusion, I recommend
that you do not use this feature.
| | 03:23 | Now, let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
|
|
7. Defining FunctionsOverview of functional programming| 00:00 | Functions are fundamental to both C
and C++, even C++ as object-oriented
| | 00:06 | programming model C functions
with the basis of class methods.
| | 00:11 | All code in a C or C++ program happens in
functions, starting with the main function.
| | 00:17 | In C and C++, functions are blocks of
code that may be called by and may return
| | 00:23 | values to other code.
| | 00:26 | This is analogous to procedures or
subroutines in other programming languages.
| | 00:30 | Functions allow you to generalize
and modularize your code by creating
| | 00:34 | containers for logical subsets of
code and by allowing code to be reused.
| | 00:41 | In C and C++ arguments are
always passed to functions by value.
| | 00:46 | So when you call a function pass it a
variable, a copy of the content of the
| | 00:50 | variable is passed to the function.
| | 00:52 | If the function then changes that
value the caller's copy remains unchanged.
| | 00:56 | For example, here we have a variable a,
with the value 1, this variable is
| | 01:02 | passed to a function f, after the
function returns we print the value.
| | 01:07 | Here is the function which takes
that value and assigns it to a local
| | 01:12 | variable also named a.
| | 01:15 | But this is absolutely a different
variable, it's in a different scope, and it's
| | 01:19 | separate in every way.
| | 01:21 | The value 1 is copied and passed to
the function, so when a is incremented in
| | 01:27 | the function only its local copy is
affected, the caller's copy remains
| | 01:31 | unchanged and the printf
will print the number 1.
| | 01:35 | The alternative to call by
value is call by reference.
| | 01:38 | To implement call by reference you must
do so explicitly, the advantage here is
| | 01:43 | you will know by reading the code that
a reference is being passed and they are
| | 01:47 | very likely be side-effects.
| | 01:49 | In this example the Ampersand of the
function call parameter means to pass a
| | 01:54 | pointer to a, instead of the value of a.
| | 01:56 | The Ampersand is called the reference
operator or sometimes the address of operator.
| | 02:02 | And in the function the variable p
carries as its value a pointer to a, so
| | 02:08 | we want to increment the value of a,
we do so by dereferencing the pointer,
| | 02:12 | the Asterisk is called the Indirection
Operator or sometimes the dereference operator.
| | 02:17 | So this time by passing a pointer
we're explicitly using call by reference,
| | 02:22 | and the value in the caller's
variable a will be incremented and the printf
| | 02:27 | will print the number 2.
| | 02:28 | In C++ you may also use the reference
type to implement call by reference.
| | 02:34 | This makes call by reference appear more
implicit, this feature is not available in C.
| | 02:39 | In C++ functions are
identified by their function signature.
| | 02:45 | In C++ this function which returns
the volume of a cuboid is different than
| | 02:51 | this function which returns the
volume of a sphere, even though the two
| | 02:54 | functions have the same name.
| | 02:56 | The return type, the name of the
function, and the types of the function
| | 03:00 | arguments are all combined to
form the function signature.
| | 03:03 | This function signature is
used to identify the function.
| | 03:07 | In C this distinction does not exist
and these two functions would cause a name
| | 03:11 | collision, because a function is
identified only by its name in C.
| | 03:18 | Understanding functions is
fundamental to both C and C++, even in C++ is
| | 03:23 | object-oriented programming model, C
functions are the basis of class methods,
| | 03:28 | all code in a C/C++
program happens in functions.
| | Collapse this transcript |
| Defining a function| 00:00 | Defining your own functions is a
fundamental part of C and C++ programming.
| | 00:05 | Let's take a look at how this is doing.
| | 00:07 | I am going to start by making a working
copy of func.c. I am going to use the C
| | 00:12 | version here, not the C++ version and
paste that into our Working project and
| | 00:17 | open it up in the editor.
| | 00:18 | Now we're using C for this example,
because it's the lowest common denominator
| | 00:24 | but this is exactly the same in both C
and C++, and it's a fundamental building
| | 00:29 | block of all C and C++ programs.
| | 00:33 | In fact, the function is the
basis of methods in C++ classes.
| | 00:38 | As you'll learn when we cover C++
classes and objects later on.
| | 00:42 | So here we have a simple
function. It's called func.
| | 00:45 | It returns void which means that it
does not return a value at all, and it
| | 00:50 | takes no arguments.
| | 00:52 | In fact, inside of the parentheses
there we could put the word void in the
| | 00:56 | definition and also down here
where it's actually defined.
| | 01:01 | The above is actually a
declaration, not a definition.
| | 01:04 | We can put the word void there, and
that would mean the same thing that it does
| | 01:08 | not take any arguments, but
this is commonly done this way.
| | 01:12 | So we're doing it this way this time.
| | 01:15 | So if we save this and run it, you'll
see that it runs the function and the
| | 01:20 | function is defined down here.
| | 01:21 | It's declared up above, and it's
defined down after the main, and it has this
| | 01:26 | printf in it that prints the words this is func.
| | 01:30 | Now the reason for this is
because it's called before it's defined.
| | 01:33 | So it's called here in main,
and it's defined here after main.
| | 01:38 | In order for that to work we have
to declare it before the place where
| | 01:43 | it's actually used.
| | 01:44 | If I were to remove this declaration,
and I can just comment it out here with a
| | 01:49 | couple of slashes and try to compile
it and run it, you see we get errors.
| | 01:55 | And these warnings, they
say implicit declaration.
| | 01:58 | Now in this case the compiler is being a
little bit forgiving, and it's allowing
| | 02:03 | us to do it, but in reality
this is not allowed at all.
| | 02:07 | So declare your functions before you use
them, and you can avoid the entire need
| | 02:13 | for a declaration by simply putting the
function above the main and defining it
| | 02:18 | there, and now when we run this we
don't need the forward declaration at all.
| | 02:22 | It just works because the entire
function is defined before it's used.
| | 02:26 | So this declaration here, which just
has the function signature, this is called
| | 02:32 | a forward declaration and these
are typically put in header files.
| | 02:36 | So that's how you define and declare a function.
| | 02:39 | We'll get into many more
details throughout this chapter.
| | 02:41 | Now let's delete our func.c from our
Working project, and we will run Clean to
| | 02:48 | get ready for the next lesson.
| | Collapse this transcript |
| Passing parameters to a function| 00:00 | Parameters are passed to functions by
declaring them inside the parentheses
| | 00:04 | of the function definition.
| | 00:06 | Let's take a working copy of func.cpp
we'll use the C++ version this time and
| | 00:12 | paste into our Working project and
open it in the editor, you see this is
| | 00:16 | exactly the same as func.c with the
difference that we're including iostream
| | 00:21 | up here instead of stdio.h. So let's
save this and run it and see there's
| | 00:26 | working that's great.
| | 00:29 | And now let's go ahead and pass a
parameter, so we'll start by changing our
| | 00:32 | function declaration, and we will save
it, its going to take an int and so we
| | 00:38 | just put the type inside of the
function signature there.
| | 00:41 | And then down here in the actual
definition we can give the int a Name, and then
| | 00:47 | we just printed inside here, I want
to say i is %d and put the i in
| | 00:56 | here, and we'll say in func so we know.
| | 01:00 | And now you'll notice that we have a
little bug mark next to our function
| | 01:04 | call here because our function
signature shows it with an int.
| | 01:08 | So given an int here we'll have to
define 1, we'll give it a value, and we'll
| | 01:15 | just put that in here.
| | 01:18 | So I'll save this and run it, and you
see we're successfully passing our integer
| | 01:24 | value into the function.
| | 01:27 | So in C and C++ functions always passed
by value, so what that means is is that
| | 01:34 | when I make this function call
with the i in it, it actually makes a copy
| | 01:39 | of that i and passes the copy
into the function and inside the
| | 01:43 | function the copy is called i
and so this is a copy that's being used
| | 01:47 | inside the function.
| | 01:49 | So if I come in here, and I say, i = 132
and then after the function call
| | 01:55 | out here I print it, save that and run
it, and you see that this i is unchanged
| | 02:02 | it's still 7, inside the function it's 132.
| | 02:07 | Now if you actually want to affect the
variable outside of the function then you
| | 02:11 | need to pass a pointer or reference.
| | 02:14 | And so here we can call this a pointer
we'll call int pointer like that and
| | 02:19 | here we'll call int pointer like that.
| | 02:22 | And now we're going to use what's
pointed at by the pointer not the pointer
| | 02:26 | itself, by dereferencing
with the deference operator.
| | 02:31 | And I need to pass an address
instead of the actual variable here.
| | 02:37 | So now I am passing the address to i,
and I am changing i inside of the
| | 02:41 | function and so we would accepted to be
change in both those printfs there, and
| | 02:47 | there it certainly is.
| | 02:48 | Now if you're using C++ you can do
this with references instead of pointers
| | 02:54 | and the advantage and disadvantage of
references is that this syntax is much simpler.
| | 02:59 | So if I change that to a reference
there, here I no longer need to send the
| | 03:05 | address, I just put the variable there
and the compiler will go ahead and create
| | 03:09 | the pointer for me and here instead
of the asterisk I am going to have the
| | 03:15 | ampersand so for it to be a reference.
| | 03:17 | And now I just use it as if it were
straight variable and not a pointer at all.
| | 03:22 | So the semantics is
different and the effect is the same.
| | 03:26 | Save this and run it, and you see we
still have our side effects, we are
| | 03:30 | still actually changing this variable, and
we just don't have all that syntax around it.
| | 03:35 | The only thing we've changed
here is the function signatures.
| | 03:39 | References are available in C++
they are not available in the C.
| | 03:44 | Now function calls always passed by
value if you pass a reference or a pointer
| | 03:48 | it's the value of the reference
or the pointer that you're passing.
| | 03:52 | References make this almost completely
invisible and therefore more prone to
| | 03:56 | error, but the function
call is still passing a value.
| | 04:00 | Now given that functions are strictly
passed by value when you are passing
| | 04:03 | something big you'll always want
to use a reference or a pointer.
| | 04:07 | For example, here if I declare a string,
that's a really big string with lots of
| | 04:12 | text in it, and I can pass that as a reference.
| | 04:20 | So now here I am going to get rid of that integer,
and I'm going to pass my string instead
| | 04:26 | and here we will just display the string here.
| | 04:31 | And down here in the function we're
going to take a string instead of integer,
| | 04:39 | we need to take the c_str of the string
in order use in printf or we could just
| | 04:45 | used a cout, like that.
| | 04:49 | And the same thing here, here we
will just take the c_str of it.
| | 04:54 | So you can see both ways to do that.
| | 04:56 | So now we'll go ahead and compile this
and run it, and you'll see we're passing
| | 05:01 | our string into the function.
| | 05:02 | Now the probably with this is, is that
we're actually passing a reference to the
| | 05:07 | string so now it's possible for the
function to actually modify the string, and
| | 05:12 | we don't necessarily need for that to happen.
| | 05:14 | So we're going to change our signature,
and it's a good habit to get in every
| | 05:19 | time you are using a reference to use
the keyword const, and this prevents
| | 05:24 | accidents from happening with side effects.
| | 05:26 | So we'll save this run it, and we see
that, that's how you pass a larger object
| | 05:32 | into a function using a reference.
| | 05:35 | Parameters are always
passed by value in C and C++.
| | 05:39 | you can pass pointers or references
if you need side effects, but you will
| | 05:42 | need to do explicitly.
| | 05:44 | So let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using automatic and static variables| 00:01 | Variables declared in a
function default to automatic storage.
| | 00:05 | Other storage options are available.
| | 00:07 | Let's make a working copy of func.cpp
and paste it in our Working project here
| | 00:12 | and open up in the editor.
| | 00:14 | I'm going come down here in our
function, and I'm just going to declare
| | 00:17 | an integer, and as I print it I am
going to also increment it, and I'll
| | 00:25 | do a posting comment on it, and that way
every time it's called it will get incremented.
| | 00:29 | And we will just call it five times here,
and we'll save that and run it, and we
| | 00:34 | get five times that it's 5, and you
will notice that each time I print I go
| | 00:39 | ahead and increment it, but the
next time I print it it's 5 again.
| | 00:42 | The reason for that is
this is in temporary storage.
| | 00:45 | Automatic storage is stored on the
stack which is created fresh for each
| | 00:48 | invocation of a function.
| | 00:50 | So the value is not carried
from one invocation to the other.
| | 00:54 | If on the other hand I declare this as
being static storage then I save that and
| | 01:00 | run it with no other changes you'll
notice that it gets incremented every time.
| | 01:05 | Static storage is not stored on the stack.
It's not temporary.
| | 01:09 | It's persistent for life of the process.
| | 01:11 | Now the value is carried
from one invocation to another.
| | 01:15 | Static storage is typically used for
keeping state and for other purposes where
| | 01:19 | you just need to keep the storage around.
| | 01:20 | Variables declared in a function default
to auto storage if you want your data to
| | 01:26 | be persistent, you may
declare your variables as static.
| | 01:28 | For more storage class options see the
movie on data type qualifiers in Chap05.
| | 01:33 | Now we'll delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using function pointers| 00:00 | Function pointers can be really
convenient in a number of circumstances, let's
| | 00:04 | take a look at an example.
| | 00:06 | Let's make a working copy of func.c,
place that in our Working project and here
| | 00:13 | we have just a simple function,
doesn't take any parameters, doesn't return
| | 00:16 | anything, and we are calling it like this.
| | 00:20 | So if we compile this and run it,
you see it prints out this is a func().
| | 00:23 | Now instead of calling it like this I
can create a pointer, and I can call it
| | 00:28 | through the pointer.
| | 00:29 | I can say void (*func) like that =
--look now I am reusing the name there--
| | 00:36 | I don't want to do that I am going to
call this fptr, and then I can run it like
| | 00:41 | this, and that will actually call the function.
| | 00:45 | So let's compile this and run it, and
we see we have exactly the same result.
| | 00:49 | So the difference here is that I've
declared a pointer, and I am calling the
| | 00:53 | function through the pointer.
| | 00:54 | The syntax of the function pointer
might look a little bit obscure, well,
| | 00:57 | it is a little bit obscure.
| | 00:59 | And you'll notice that the pointer
operator and the name of the function are
| | 01:03 | inside of parentheses, and that's like
that because of operator precedence and
| | 01:07 | then the function operator is on
the outside of the parentheses.
| | 01:10 | So this indicates that we have a
function pointer, and we call it with
| | 01:14 | exactly the same syntax.
And that's true with so many other things.
| | 01:17 | We do reference a pointer with exactly the
same syntax that we declare a pointer with.
| | 01:22 | So that's what a function pointer looks like,
and that's how a function pointer works.
| | 01:27 | Let's take a look at this in action,
see what it might actually be useful for.
| | 01:30 | We'll close this, and we'll delete our
working copy of func.c and run Clean,
| | 01:36 | because we are going to use
a different source file here.
| | 01:40 | And I am going to bring in jump.c, so
we'll copy that and paste it into Working
| | 01:46 | project and bring it up here.
| | 01:48 | I am going to walk through this in a
second here, let me just show it to the
| | 01:53 | folks who might be typing along at home.
| | 01:55 | Now I am going to compile this and
run it, and you'll see what it does.
| | 01:59 | It basically puts up a menu.
| | 02:00 | I am going to maximize this so
you can see what it does here.
| | 02:02 | And if I type a 1, Eclipse is a
little bit funny with this, you'll notice
| | 02:06 | that the cursor is up at the top but when I
press the 1 it actually goes after the prompt.
| | 02:10 | That's just Eclipse, on a real
console this will work just fine.
| | 02:14 | I am going to press 1, and you'll see
it runs Function a, which says this is a.
| | 02:18 | And if I press a 3 you see it
runs function c, it says this is c.
| | 02:23 | If I press something out of range, if I
press like a 7 it says invalid choice.
| | 02:28 | And if I press q, it will actually quit.
| | 02:32 | So let's bring this back down, and let's take
a look at the code and see how all this works.
| | 02:38 | So we have these five little
functions here, and then we have forward
| | 02:41 | declarations for a couple of
functions that we'll look at later.
| | 02:44 | And then what we have here on line 13
is we have an array of function pointers.
| | 02:49 | The array is called funcs, and you'll
notice that inside that first set of
| | 02:55 | parentheses there is the asterisk
which indicates it is a pointer,
| | 02:58 | there's variable name which is funcs.
| | 03:01 | And there is the square brackets, which
means that it's declaring an array, and
| | 03:07 | then we close out those parenthesis,
and we have the function operator on the
| | 03:11 | outside, and this basically says that
well this is the way that you declare an
| | 03:15 | array of function pointers.
| | 03:17 | Then we initialize the array of
function pointers with the addresses of these
| | 03:22 | five functions and a null pointer to
terminate the array, because this is C,
| | 03:26 | it's not C++, and this is not an
object vector, this is a simple C-array with
| | 03:33 | five pointers in it and a null pointer.
| | 03:37 | Then main calls the function prompt,
and then it says done when it's done
| | 03:41 | because prompt will turn around and call
jump, which actually uses this jump table.
| | 03:45 | So this structure, this array of
function pointers is sometimes called jump
| | 03:49 | table, and it can actually be really,
really convenient for console-based
| | 03:52 | applications that use a menu, or I've
even used in CGI applications where I
| | 03:59 | have a number of different possible options
that depend on a variable getting past through CGI.
| | 04:04 | So there is the prompt function which
basically puts out the prompt which is
| | 04:09 | that menu and the little prompt
characters there, and it gets the response using
| | 04:15 | fgetln, and it calls jump, and it
returns the return value from jump.
| | 04:20 | Now the jump function, this is
where the work is actually done.
| | 04:24 | It takes the response from the keyboard,
and it decides if it's a q or not, and
| | 04:29 | if it's a q then it returns 0,
which means that we're done.
| | 04:33 | And otherwise it uses this little for
loop to get the length of the array.
| | 04:38 | Line 47 is just a little trick for
converting a character into an integer.
| | 04:43 | The first character of the response string,
| | 04:45 | it simply subtracts the value of 0 of
the ASCII character 0, and then it's got
| | 04:51 | an integer, it's got a 0 based integer.
| | 04:53 | And it checks to make sure that it's a
valid number that less than 0 or greater
| | 04:57 | than 8 is checking to make
sure it's a valid number.
| | 05:00 | We've decremented 1, because our number 1 is
going to be the zeroth element of our array.
| | 05:06 | And then down here starting at line 54,
we check to see if we are in range, if
| | 05:11 | we have that many elements in our array.
And if so, we go ahead and call the function.
| | 05:16 | And on line 55 there, it's calling the
function from the array, so we have i as
| | 05:22 | the index into the array and the
function operator at the end, the parentheses
| | 05:28 | tells it to call the
function based on that pointer.
| | 05:30 | So this is a really, really simple way
to implement a menu in a console-based
| | 05:35 | application or to implement any kind of
a jump table where you might want to be
| | 05:40 | calling different
functions based on a piece of data.
| | 05:43 | Now of course this works just as
well in C++, and let's just take a quick
| | 05:49 | look at this in C++.
| | 05:50 | We are going to go ahead and delete our
working copy of jump.c, and we will run
| | 05:54 | Clean, and we'll make a working copy
of jump.cpp and paste it here into our
| | 06:00 | Working directory and
open it up, and we'll run it.
| | 06:04 | And you can see here this works exactly
the same, if I type 1 I get this is a, 2
| | 06:10 | this is b, 5 this is e.
If I type 6, I get invalid choice.
| | 06:16 | If I type a q, it quits.
| | 06:18 | So this works exactly the same,
it's mostly the same code.
| | 06:22 | You'll see our functions look exactly the same.
| | 06:25 | Instead of our jump table in an array
we're actually using an STL vector here,
| | 06:31 | and we'll cover this in the chapter on STL,
but basically that's how you declare a vector.
| | 06:36 | And the type is a pointer to a void
function so that's the type that goes in the
| | 06:41 | template for the vector.
| | 06:43 | We just have the 5 here because this is
a vector, and it knows how long it is we
| | 06:47 | don't need that terminator.
The Prompt is pretty much the same,
| | 06:50 | we are using cout instead of printf,
because this is really convenient to be
| | 06:54 | able to do cout like that, all in
one statement with one semicolon.
| | 06:59 | And our string response cin, this is
actually all a whole lot simpler than it is in C.
| | 07:04 | And our jump function is
almost exactly the same.
| | 07:08 | You notice we are able to test against
the size of the vector using the size
| | 07:13 | method out of the vector, so we
don't have to figure how long it is.
| | 07:16 | And we are calling it, exactly the same
way that we would call it out of the array.
| | 07:21 | So that's how you create a jump
table using an STL container in C++.
| | 07:26 | So function pointers can be really
useful, you're not going to need them often,
| | 07:30 | but when you do it's really
convenient to know how to use them.
| | 07:33 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Overloading function names| 00:00 | In C++ it's possible to have
different functions with the same name.
| | 00:04 | The compiler selects would function call
based on the entire function signature,
| | 00:08 | not just the function name.
Let's take a look at this feature.
| | 00:12 | We will open func-overload.cpp, and
we'll paste that into the Working project
| | 00:19 | and double-click on it to open it in the editor.
| | 00:22 | I'll just maximize this so we can take a look at it
and scroll down so you can see the whole thing.
| | 00:29 | In this program you'll notice I have
three functions, each of them called volume.
| | 00:36 | They differ by their function signatures.
| | 00:37 | A function signature includes the return type,
the function name, and the type and number of parameters.
| | 00:44 | So here we have int volume int, here we
have double volume double int, and here
| | 00:50 | we have long volume long, long, long.
| | 00:53 | So those are three different functions in C++.
In C this just does not work.
| | 00:57 | In C functions are identified only by
the function name, and this would cause a
| | 01:01 | name collision, and it would not compile.
But here it works fine.
| | 01:05 | The first one calculates the volume of
a cube, and it only takes one integer
| | 01:09 | for the dimensions of the one side and all three
dimensions of a cube are the same by definition.
| | 01:15 | The second one calculates
the volume of a cylinder.
| | 01:18 | So it takes the radius and
the height of the cylinder.
| | 01:22 | And the third returns the volume of a
cuboid where the length, width, and height
| | 01:27 | are all different numbers, and it simply multiples
them together and returns the volume of the cuboid.
| | 01:32 | So they're all called volume, and you
can see down here in main where they're
| | 01:36 | called, this one is just called with
one integer, this one is called with a
| | 01:41 | floating point and an integer, and
this one is called with three integer.
| | 01:45 | So the compiler knows which one based on the number
and types of parameters, it knows which one to call.
| | 01:53 | So let's go ahead and run this.
| | 01:56 | Compile and run, and we see cube of 2 is 8,
cylinder of 2 x 2 is 25.1327, and a
| | 02:05 | cuboid of 2 x 3 x 4 is 24.
| | 02:09 | So there are some rules to this,
like the return type cannot be the only
| | 02:12 | distinguishing factor, but the constant
of the return type can be and often is.
| | 02:17 | And there are rules about how types are
promoted to distinct parameters, so it's
| | 02:20 | a good idea to test your overloaded
functions thoroughly, and keep in mind that
| | 02:24 | none of this applies to C.
| | 02:26 | In C a function is distinguished only by
its name, and this example would not compile.
| | 02:31 | So in C++ functions are
distinguished by their function signature.
| | 02:35 | So it's possible to have multiple
functions with the same name that operate with
| | 02:39 | different parameters and with return types.
| | 02:42 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Overloading operators with functions| 00:00 | When you're dealing with simple built-in
scale or values, it's usually pretty
| | 00:04 | obvious what most operators will
do, 2+2 will generally get you 4.
| | 00:09 | But when you're dealing with
classes in C++, it's not obvious at all.
| | 00:13 | In fact, C++ operators don't work
with classes unless you tell them how.
| | 00:18 | For this purpose, you'll want to write
your own code for some operators, this is
| | 00:21 | called Operator Overloading.
| | 00:23 | There are basically two ways to
overload operators in C++, one is with class
| | 00:28 | methods, the other is with functions.
| | 00:31 | In this movie, we'll discuss
overloading operators with functions.
| | 00:34 | We'll discuss C++ class methods in
the chapter on C++ classes and objects.
| | 00:40 | Let's make a working copy of func-operator.cpp,
and I'll paste that into my
| | 00:46 | Working Project and open it up in editor.
| | 00:48 | I'm going to double-click on this to
maximize it so that we can see the entire file.
| | 00:54 | Here we have a simple
contrived class called class A.
| | 00:59 | Down here in main I'm declaring two objects of
class A, one of them is a is one of them is b.
| | 01:05 | One of them has a value 5,
and one of them has a value 42.
| | 01:08 | This class simply contains an integer
and initializes the integer and will
| | 01:12 | return the value with the class method value.
| | 01:16 | So if we want to add these two
objects together like on line 20, we need to
| | 01:20 | overload the Plus operator.
| | 01:22 | So there in line 12 is the operator
overload, and it's constructed like this:
| | 01:26 | int is the return value, the operator
keyword tells the compiler that this is an
| | 01:33 | operator overload, and then the Plus
symbol is the operator being overloaded.
| | 01:38 | The parameters left-hand side and
right-hand side are both references to an
| | 01:43 | object of class A, and on line 14 we
use the value method which is called an
| | 01:50 | accessor, because it's used
to access a private variable.
| | 01:53 | So we use the value method to get the
value of the integer a from inside the
| | 01:59 | class A, that integer is declared on
line 6, and we add those two values
| | 02:04 | together and return the result.
| | 02:07 | So it's really a very simple
function, and it works effectively.
| | 02:10 | Let's go ahead and run it.
| | 02:12 | Bring this back down to size, and I'm
going to click on the big green Compile
| | 02:17 | and Run button, and you see here the first
line of our results says "operator + for class A",
| | 02:23 | and that's simply this cout on
line 13, and then it returns a value.
| | 02:28 | That just tells us that
the method is getting called.
| | 02:31 | And where is that method getting
called? It's getting called right here.
| | 02:35 | When we add up these two objects, the
Compiler sees that, and it looks for an
| | 02:40 | operator + overload that takes those
two types as its arguments, and so here
| | 02:45 | we have left-hand side and right-hand side,
and so it calls that function, and it
| | 02:50 | returns the value as the
result of that expression.
| | 02:55 | So this feature of course is not
available for built-in types, so I can't create
| | 02:59 | an Operator Overload for two ints, for example.
| | 03:02 | Well, I can see where that may be an
entertaining thing to do, it wouldn't
| | 03:06 | really be useful or a very good idea.
So you can see this is pretty easy to do.
| | 03:10 | As I said, this is only half of the story.
For the rest of it be sure to watch
| | 03:15 | the movie on Operator Overloading in
the chapter on Classes and Objects.
| | 03:19 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Defining a variable number of arguments| 00:00 | For those times when you need a
function that may take a varying number of
| | 00:04 | arguments, C and C++ provide variadic functions.
| | 00:07 | Let's get a working copy of variadic.c,
and we'll paste this into the Working
| | 00:13 | project, and I'll go ahead and maximize
this by double-clicking on that tab at
| | 00:17 | the top, and scroll down so
you can see the whole thing.
| | 00:21 | So, you notice on line 3, I'm including
a header called standard arg dot H, stdarg.h.
| | 00:28 | In C++, the equivalent header is cstdarg.h,
and of course, this technique works in both C and C++.
| | 00:37 | We're showing the demonstration in C this time.
| | 00:39 | So this file shows two
examples of variadic functions,
| | 00:43 | an average function for computing
the average of a variable number of
| | 00:47 | arguments, and a message function that
actually passes the variadic arguments
| | 00:52 | on to another function called vfprintf, and this
is actually how functions like printf are implemented.
| | 00:59 | So, starting with the average function,
you'll notice on line 7, I declare a
| | 01:03 | variable called ap that's of type va_list.
| | 01:06 | va_list is actually a macro that's used
for implementing the variable argument list.
| | 01:13 | Every function that uses a variable
argument list must declare a variable of
| | 01:16 | this type, and must also
call va_start and va_end.
| | 01:20 | va_list, va_start, and va_end are defined
in stdarg. va_list is actually a typedef.
| | 01:27 | So, on line 11, we call va_start,
and this is actually a macro.
| | 01:31 | The first argument is the va_list
itself, and the second argument is the last
| | 01:36 | parameter in the
parameter list before the "...".
| | 01:40 | Now, looking at our parameter list,
you'll notice that, that "...", that
| | 01:45 | indicates the variable argument
list, and that's actually three dots.
| | 01:49 | It's not a single character that
represents an ellipsis that you might get as an
| | 01:54 | automatic replacement in a
text editor or a word processor.
| | 01:56 | This is actually three dots, there's no
space between the dots, and these three
| | 02:00 | dots must be the last thing in the argument list,
and it cannot be the first thing in the argument list.
| | 02:06 | So, there needs to be at least
one other variable before it.
| | 02:09 | And this is so that va_list can do its magic.
| | 02:14 | And so in va_start, you notice that we
pass it that last argument before the
| | 02:19 | three dots in the argument list, and
this tells va_start the thing right after
| | 02:25 | that is where the variable argument list begins.
| | 02:28 | In line 13, we get the next argument
in the list with va_arg, and we give it
| | 02:33 | the va_list variable, and we also give it
the type of what that argument is going to be.
| | 02:39 | That will get returned by va_arg.
Then in line 15, we call va_end.
| | 02:44 | Every va_start must be matched by a va_end.
If you don't do that, you may get leaky code.
| | 02:52 | Before we go and run this and test it, I want
to show you also this other function on line 19.
| | 02:58 | This is another type of
variable argument function.
| | 03:01 | This one is called message, and it
actually calls another function called
| | 03:05 | vfprintf and passes it
that variable argument list.
| | 03:10 | So, here on line 20, of course we
declare the variable of va_list type.
| | 03:15 | On line 21, we call va_start.
| | 03:18 | We pass it fmt, or format which is the
last argument before the variadic list.
| | 03:23 | Then on line 22, we pass all of
that to the vfprintf function;
| | 03:29 | vfprintf function is actually how
functions like printf are implemented, and it
| | 03:35 | takes the standard out, and a
format, and a variable argument list.
| | 03:40 | And it then prints those results to standard
out or to whatever file handle you pass it.
| | 03:45 | Then you'll notice on line 24, there's a
matching va_end for the va_start on line 21.
| | 03:52 | Then down in the main function, we call
message once with just a message, and no
| | 03:57 | variable argument list at
all, and that works fine.
| | 03:59 | Then on line 30, we call message, and we
pass it the results of average, which is
| | 04:05 | its own variable argument list.
| | 04:07 | The first number is the count of
arguments, and the next five arguments are
| | 04:13 | floating-point numbers which get
passed to the variadic function.
| | 04:18 | So now, let's go ahead and bring this
back down to size, and we'll press the big
| | 04:22 | green Compile and Run button.
| | 04:24 | You'll see first line is "This is a message",
and second line is the average of
| | 04:29 | these five floating-point numbers.
| | 04:31 | And of course that function gets
passed to five, which is the count of the
| | 04:35 | arguments in the variadic list.
| | 04:38 | So for those times when you need a
function that may take a varying number of
| | 04:41 | arguments, C and C++ provide variadic
functions, and that's how they work.
| | 04:47 | Let's go ahead and delete our Working file and
run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using recursion| 00:00 | A recursive function is a
function that calls itself.
| | 00:03 | Let's take a look at an example.
| | 00:05 | Let's open up recursive-factorial.cpp,
we'll copy that and paste it into our
| | 00:11 | Working project and double-click
on it to open it in the editor.
| | 00:15 | This is an example of a very simple and--a very
common example actually--of a recursive function.
| | 00:21 | A factorial in math is typically
defined in recursive terms.
| | 00:24 | It is the product of n(n-1)(n-2),
all the way down to 1.
| | 00:31 | So here if you look at how this
function works, it first tests if n is less than
| | 00:35 | than 2, and if it does, it just returns
a 1 because we know the answer to that.
| | 00:40 | And if not, it goes ahead and it
returns the factorial of (n-1)n. And in order
| | 00:47 | to get the result of the factorial (n-1)
it has to call itself, and it passes at
| | 00:52 | n-1, and that will happen over and
over until n is 1, or less than 2.
| | 00:59 | So let's go ahead and run this by
pressing the big green Compile and Run button,
| | 01:03 | and you'll note that the
factorial of 10 is 3,628,800.
| | 01:09 | This actually called itself ten times.
| | 01:12 | Now there is a limit to how many times
you can do this, obviously there is a
| | 01:17 | limit of the size of unsigned long
integer, but there is also the limit of the
| | 01:22 | amount of resources that
are available on the computer.
| | 01:24 | Every time you call a function,
memory is allocated for the parameters, for
| | 01:30 | any local variables, and for the return value
and all the other function called overhead.
| | 01:35 | If you do this recursively, it could
happen many, many times, and all of
| | 01:39 | those resources keep getting allocated
and not deallocated until the last one
| | 01:44 | is returned, and then all of those resources
get deallocated, so this can be very inefficient.
| | 01:51 | So if you have a choice between a
recursive function and a function that works
| | 01:56 | with a loop, oftentimes the
loop will be a lot more efficient.
| | 01:59 | For example, for this function I could
do it like this. Of course that first
| | 02:05 | line is going to stay the same.
| | 02:08 | We can declare a variable for our
result and our starting place is n.
| | 02:14 | And then there is a simple while loop.
| | 02:16 | So for every value of n > 1 it will
multiply the result by the decrement of n.
| | 02:23 | So first it'll decrement n, and then it'll
multiply the result for each one of those.
| | 02:27 | And then it'll return result. We see that
the result is exactly the same, 3,628,800.
| | 02:36 | Now this version of the function
takes up a lot less resources.
| | 02:39 | It simply allocates all the stuff that it
allocates for one function call, and it
| | 02:43 | allocates one more long int, and then it
sits there and loops and multiplies the
| | 02:49 | result for a moment, and it returns that result.
| | 02:52 | Whereas the recursive version
allocates everything that's necessary for the
| | 02:56 | entire function call as
many times as the value of n.
| | 03:00 | So C and C++ support recursive functions,
but you should be careful for problems
| | 03:06 | that may require a lot of iterations.
Recursion can quickly use up a lot of
| | 03:10 | resources, it's often better
to find a different solution.
| | 03:13 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
|
|
8. Classes and ObjectsOverview of classes and objects| 00:00 | In C++, classes are like custom data types.
They are designed to be used just
| | 00:05 | like the fundamental types
provided by the C++ language.
| | 00:09 | Let's start by defining the terminology
that we will be using in this section.
| | 00:13 | First, let's look at the words class and object.
| | 00:17 | The definition of a class, using
the class keyword is the class itself.
| | 00:22 | You can then use the class to declare an object;
| | 00:25 | the object is also
called an instance of a class.
| | 00:28 | Sometimes you'll hear the verb form instantiate
to describe the process of creating an object.
| | 00:35 | Members are the contents of an object.
There are two types of members.
| | 00:39 | Data members are the members that
represent the encapsulated data.
| | 00:44 | Data members are sometimes called properties.
| | 00:47 | Function members are members that
represent functions associated with the class.
| | 00:52 | Function members are sometimes called methods.
| | 00:55 | Constructors and destructors are
special function members that are called when
| | 00:59 | an instance of an object is
created or destroyed respectively.
| | 01:03 | A constructor is called when the
object is created. There may be several
| | 01:07 | constructors defined, but only one is
called depending upon how the object is created.
| | 01:13 | The destructor is called when the object is
destroyed. There may only be one destructor defined.
| | 01:18 | C++ classes are based upon the C struct.
In fact, a C++ class is identical to a
| | 01:26 | struct with one difference.
| | 01:27 | In a struct, members default public access,
whereas in a class members default private access.
| | 01:34 | This matches how they are commonly used.
| | 01:36 | If you're looking to access data
members directly, you probably want a struct.
| | 01:41 | Because the members of a class default to private,
accessing those private members is not allowed.
| | 01:45 | Of course, you could set the members to
public access, but if you're going to
| | 01:49 | use it as a struct you should
probably just declare it as one.
| | 01:53 | If you're using a class, you'll probably
want to define accessor methods for data
| | 01:57 | members you want access to.
| | 01:59 | Accessor methods are function members designed
to set values in and get values from the data members.
| | 02:06 | These accessors are
sometimes called getters and setters.
| | 02:10 | It's good practice to use the struct
keyword for plain old data structures,
| | 02:14 | sometimes called pods, and to use the
class keyword for classes with member functions.
| | 02:19 | C++ classes allow you to create fully-realized
types that work exactly how you want them to.
| | 02:26 | Using C++ classes you may create constructors for
a variety of different types and numbers of parameters.
| | 02:33 | You can even disallow the default
constructor if that makes sense for your class.
| | 02:38 | You can allocate and deallocate memory
appropriately so that your objects run smoothly.
| | 02:44 | Overload operators so that your objects
can use those operators intelligently.
| | 02:49 | Overload the function operators so that
your objects can operate like a function
| | 02:53 | itself, or you can create conversion
operators so that your objects behave as you
| | 02:58 | expect them to in different contexts.
| | 03:01 | The C++ class model allows you to
define rich and complex data types and use
| | 03:06 | them just as you would a
fundamental built-in type.
| | 03:09 | In this chapter we will cover how to define
and use these features in your own classes in C++.
| | Collapse this transcript |
| Exploring namespaces| 00:00 | As we begin to create lots of classes and objects,
the possibility of naming collisions increases.
| | 00:07 | Namespaces in C++ are a
great tool for managing this.
| | 00:11 | Let's take a working copy of namespace.cpp.
| | 00:14 | I'll copy that and paste it into our
Working project and open it up in the editor.
| | 00:19 | I'll just maximize this so
that you can see the entire file.
| | 00:23 | You notice on line 3, it
says namespace BWString.
| | 00:28 | We'll cover the details of the classes
and methods and things like that in the
| | 00:33 | rest of this chapter, but we're just
concentrating right now on the namespace.
| | 00:36 | So you notice I declare a namespace
BWString, and then there's an open curly
| | 00:41 | bracket, and then on line 15 is
the matching closing curly bracket.
| | 00:45 | The closing curly bracket on line 13
actually matches the opening on line 7 and
| | 00:51 | unfortunately it's just
the way that Eclipse works.
| | 00:55 | So, inside of those curly brackets between
line 4 and line 15 is the namespace BWString.
| | 01:02 | So everything inside of that curly
bracket that doesn't have another namespace
| | 01:07 | declared as in the case of the string
on line 6 and on line 8.
| | 01:12 | Everything else is in the namespace BWString.
| | 01:17 | So I'm going to bring this back down
to size here, and we're going to ahead
| | 01:21 | and we're going to look at the usage
of all of this line 17 through 24, and
| | 01:28 | we'll just go ahead and we'll do the
compile and run, and we'll see what happens here.
| | 01:32 | On line 17, I declare a
BWString version of string.
| | 01:36 | I give it the name s1, and I initialize it
to This is a string, but if we look
| | 01:41 | at the code for the string class in the
BWString namespace--and that begins on line 7--
| | 01:48 | you'll see that the constructor on
line 10 and the constructor on line 11,
| | 01:54 | they both simply set it to the constant
string bws, which says "This is BWString::string".
| | 02:01 | And so no matter what we initialize
this to, even in this case, initializing it
| | 02:06 | to This is a string, it's always
going to say This is BWString::string.
| | 02:11 | So if instead I take off this BWString
here, and I change it to std, which is our
| | 02:17 | standard namespace, and I compile and
run this again, you'll see that now I get
| | 02:23 | a standard string which says This is a string.
| | 02:25 | By using the BWString namespace, I'm
actually able to declare a class that has
| | 02:31 | the same name as a class in
the standard namespace, string.
| | 02:35 | We can differentiate it by
using the namespaces here.
| | 02:38 | So you notice that I don't have in
this anywhere using namespace std;
| | 02:44 | which we normally have at the
beginning of all of our C++ files.
| | 02:48 | So see I don't have that up here
because I'm actually using several namespaces.
| | 02:53 | I could--if I wanted to--I could say
using namespace BWString, and then I
| | 03:00 | wouldn't need this at all.
| | 03:02 | And then when I declare a string, I
get the BWString, and I'm going to save
| | 03:07 | this and run it, and you see that we get the
BWString version because I said using namespace BWString.
| | 03:13 | So using namespace means from here to the end of
the file--or until we see another using statement--
| | 03:19 | I am going to be using this
namespace unless I say otherwise.
| | 03:23 | So here I've actually declared a standard
string and standard cout and standard endl.
| | 03:28 | Those names, those tokens
actually exist in the standard namespace.
| | 03:32 | And so since I haven't declared using
namespace standard like we normally do, I
| | 03:38 | actually have to specify those.
| | 03:40 | If I take those off, if I were to remove this one
here, it wouldn't be able to find that symbol.
| | 03:45 | You see right there, symbol
cout could not be resolved.
| | 03:50 | Instead of using namespace BWString,
it's also possible--and you don't see this
| | 03:54 | as often but I want to
show you that how this works.
| | 03:57 | You can say using BWString::string;.
Every time it sees the word string,
| | 04:01 | it'll look in the BWString namespace, but it won't
look for other things in the BWString namespace.
| | 04:07 | So if I were to take out this one here,
for example, it wouldn't find that one
| | 04:11 | but I could say using std::cout,
and that would find both of those.
| | 04:17 | I'll Save that and run it, and click
the Run in Background button there.
| | 04:23 | So you see that it's looking for
string in the BWString namespace, and it's
| | 04:26 | looking for cout in the standard namespace.
| | 04:30 | So if I remove these, which is actually
the more common way to do it, and it's
| | 04:34 | more explicit, I can specify which one is which.
| | 04:37 | And you'll often see code written
without any using statements at all.
| | 04:42 | So we'll save this and compile and run it.
There we have it.
| | 04:48 | Namespaces are very valuable in C++,
and they are very commonly used.
| | 04:52 | Typically, they're defined in header files
with the class definitions that use them.
| | 04:57 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Defining a class| 00:00 | Classes in C++ are very powerful and flexible.
| | 00:04 | This is the fundamental unit
of object-oriented programming.
| | 00:07 | So let's take a working copy of class.cpp, and
we will paste it into our Working project here.
| | 00:14 | I'll go ahead and double-click on
that and open it in the editor, and we'll
| | 00:18 | double-click on the tab there to
maximize this so you can see the entire thing.
| | 00:22 | So here we have a very simple
class definition beginning on line 6.
| | 00:25 | You notice it has one data member, int i,
it's a private data member because
| | 00:30 | it's not specified otherwise, and members
in classes in C++ default to private access.
| | 00:38 | We have two public members, and you can
see they are declared as public on line 8.
| | 00:42 | And those public members are both function
members and they're called setters and getters.
| | 00:47 | One gets the value of i
and one sets the value of i.
| | 00:51 | So you can see these are defined just
as normal functions would be defined.
| | 00:56 | setValue returns void, and it takes
a value as an argument and integer.
| | 01:02 | And it assigns i to that integer, and
i is the private member in the class.
| | 01:08 | So this member function has access
to the private members in the class.
| | 01:14 | The next one returns an int getValue,
and it simply returns the value of i.
| | 01:21 | So that's our very, very simple class.
We can see it's used at line 15.
| | 01:26 | An object is declared using that class, so
this is called Instantiation, that's an
| | 01:31 | instance of that class,
it's an object of that class.
| | 01:34 | And on line 17 we actually call the
member function setValue with the value of i
| | 01:40 | from main and i from main is 47.
This is not the same as i from the class.
| | 01:45 | The i from the class is not visible
here at all, because it's a private member.
| | 01:51 | And so object1.setValue, that calls the
setValue method in the object1 object,
| | 01:59 | which is of type Class1.
| | 02:01 | And it passes the value of i,
which is that i = 47 from line 14.
| | 02:07 | And then cout calls object1.getValue to get
the value, and it should print value is 47.
| | 02:14 | So let's go ahead and compile this and
run it, and you see it says value is 47.
| | 02:22 | Normally it's considered best practice
to separate interface and implementation,
| | 02:25 | and what that means is that these functions
here, these are actually implementation.
| | 02:30 | The function signatures of them,
that's considered interface.
| | 02:35 | But the actual code, that's
considered an implementation.
| | 02:38 | So, typically how this is done is we
take these and move them down here and
| | 02:43 | leave inside the class, we would leave
just the function signature, and if we
| | 02:48 | take off that actual function definition,
then when need a semicolon here.
| | 02:52 | So I'm going to do the same with getValue.
| | 02:56 | And then we have two functions out here,
let's go ahead and format them like we
| | 03:00 | would in normal functions.
| | 03:02 | Now you notice we have syntax errors
here, because symbol i could not be
| | 03:07 | resolved for both of these.
| | 03:08 | And that's because the compiler does
not yet know that these are actually
| | 03:12 | implementations of methods
that are defined in class Class1.
| | 03:17 | And we tell it that by giving the
name of the class and two colons
| | 03:21 | as if it were a namespace.
| | 03:23 | Name of that class has a 1
on it, and there we go.
| | 03:26 | So I'll take that, and I'll copy
that, and I'll paste it down here.
| | 03:31 | And now the compiler knows that these
are implementations of function members of
| | 03:36 | methods that are defined as part of Class1.
| | 03:40 | So up here from line 6 through 11, we
have the interface, and that tells us
| | 03:45 | how our class is used.
| | 03:47 | And then in lines 13 all the way down
to line 19 we have the implementation.
| | 03:53 | This is the code that
actually makes the class work.
| | 03:56 | Now normally all of this would be in
really three separate files.
| | 04:00 | I'll maximize this again.
We can look at it.
| | 04:03 | The class definition, the interface,
would be in a header file, and it would be
| | 04:09 | probably named Class1.hpp.
| | 04:12 | And the class implementation would be
in a separate file called Class1.cpp.
| | 04:19 | And those would get compiled together
and they would get linked with the code
| | 04:23 | that actually calls it, and that
would be in one or more other cpp files.
| | 04:27 | But for our purposes, for teaching
purposes, as you're learning the basic
| | 04:32 | syntax of C++ classes, we're going to be
using really simple examples, and we're
| | 04:36 | going to be putting them all in one
file like this just so that you can see how
| | 04:40 | all this stuff works, and it makes it
simpler for our purposes. Just know that
| | 04:44 | normally these things
would be in separate files.
| | 04:48 | So let's go ahead and save this and run
it, and you can see that it works just
| | 04:51 | fine, and it works exactly as we expected.
| | 04:54 | So sometimes we'll do it this way
with the implementation separate from the
| | 04:58 | class, most of the time we'll do it
that way, but it'll all be in one file, and
| | 05:03 | occasionally just for simplicity's
sake, we'll go ahead and put the
| | 05:05 | implementation if it's really small.
| | 05:07 | Oftentimes we'll go ahead and put
that inside the class definition.
| | 05:10 | That usually happens for constructors
in very, very small functions.
| | 05:14 | So let's go ahead and delete our Working file, and
we'll run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using data members| 00:00 | C++ objects are based on C structures.
| | 00:03 | In fact, you can create objects using
either the struct or object keyword.
| | 00:08 | Let's open up working.cpp out of the
Chapter08 folder in your exercise files and
| | 00:15 | double-click on it to open it in the editor.
| | 00:17 | I'm just going to go ahead and declare
a C type struct using the struct keyword
| | 00:24 | called struct A, and we'll
just give it a few members here.
| | 00:30 | And then when I come down here in the
main function, and I'm going to create an
| | 00:35 | object based on that structure.
| | 00:36 | If I just say A a = and initialize it,
I am going to use printf, and we'll see
| | 00:47 | that when I save this and press
the button there to Compile and Run.
| | 00:51 | You see that that works just fine
so I'm able to create the structure.
| | 00:55 | I'm able to create an instance of that
structure or a variable of that type,
| | 01:00 | and I'm able to access the data
members of that structure simply with the
| | 01:06 | structure member operator.
| | 01:08 | Couple of other things to notice here,
you'll notice that I didn't have to
| | 01:12 | type struct A like this.
| | 01:13 | In C, you have to type struct A as the type.
| | 01:17 | In C++, you can just use the name there,
and you don't need the keyword struct
| | 01:23 | or the keyword object.
| | 01:25 | The distinction between structures and
classes, there's really only one distinction.
| | 01:30 | If I change this to class and save it
and run it, the only reason this doesn't
| | 01:37 | work is because these data members are
private. See, it says ib is private, ic is
| | 01:43 | private, could not convert and
within this context, that means that these
| | 01:48 | private data members, I'm trying
to access them in that context.
| | 01:53 | And if we look at the actual error
message out of the compiler, we see ia is
| | 01:58 | private and then within this context
for line 13 and character position 45,
| | 02:04 | character position 51 and 57 and
those are these separate usages.
| | 02:09 | So that's the only difference. In fact,
if I were to just type public here like
| | 02:14 | this--and this declares that
these data members will be public--
| | 02:19 | this now will work exactly like the
struct, and if I can compile and run that,
| | 02:23 | everything works exactly as we expected.
| | 02:25 | Really, the only distinction between
class and struct is that data members in a
| | 02:30 | class default to private and data
members in a struct default to public.
| | 02:35 | I'm going to go ahead and
make these public again.
| | 02:37 | We can actually declare any type in here.
| | 02:40 | This middle one could be a string
called sb, and then now printing it out needs
| | 02:47 | to be a type s, and we need to actually
use the c-string method of that string.
| | 02:52 | This is actually a sb now and c_str() method,
and that will allow us to print that out.
| | 03:01 | I'm just going to put all these on
the next line so that we can see them.
| | 03:06 | c-string is a method of the String
class, and it gives us back a c-string
| | 03:09 | that's usable with printf.
| | 03:11 | And now when I initialize it--we'll
just give it a string that says two--and if
| | 03:17 | I save this and run it, you'll see
that it works exactly as we expected.
| | 03:22 | But typically, most data members
are kept as private in a class.
| | 03:27 | If you want public data members, you
probably want a struct. If you want a
| | 03:31 | class, you probably want private data
members, and you want to use accessors.
| | 03:34 | Accesssors are public function methods
that are used to access private data members.
| | 03:41 | And for an example we can
just bring up this accessors.cpp.
| | 03:44 | I'm just going to double-click on it
here. We are not going to actually compile
| | 03:47 | and run this because we're going to
cover function members in our next movie.
| | 03:51 | But I just want you to see that
this is typically how this is done.
| | 03:54 | Here's exactly the same class that we have
in the movie that we're looking at right now.
| | 03:59 | And you see we have an integer, a
string, and an integer, and then we have these
| | 04:03 | public methods for dealing with it.
| | 04:06 | We have a constructor, we have setters--seta,
setb, setc--and we have getters, geta, getb--
| | 04:12 | getb is a c-string--and getc.
| | 04:16 | And so we're actually able to do the
same thing here and use it in the same way,
| | 04:22 | but we're using function members to
access these data members, and that's
| | 04:26 | typically how it's done in a class.
| | 04:29 | So if you actually want publicly accessible
data members, then you probably want to struct.
| | 04:34 | If you want to use the encapsulation of
object-oriented programming, then you want to use a class.
| | 04:40 | You want to have private data members,
and you want to use function methods as
| | 04:44 | accessors to access those private data members.
| | 04:48 | And again, we'll learn more about
member functions in the next movie.
| | 04:51 | So I'm going to close this, and
we'll bring this back down to size.
| | 04:55 | C++ classes are based upon C structures.
| | 04:59 | In fact, C++ structures and classes are
identical except the structure members
| | 05:03 | default to public access where
class members default to private access.
| | 05:07 | It's good practice to use struct when
the structure will have only data members,
| | 05:11 | and it's good practice to use class
when there are also function members.
| | 05:16 | So let's now delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Working with member functions| 00:00 | C++ classes can have member
functions that act as methods for the class.
| | 00:06 | Let's go ahead and make a working copy
of working.cpp. We'll paste this into our
| | 00:10 | Working project and open it in the editor.
| | 00:12 | I'm going to go ahead and just create
a quick and simple little class here,
| | 00:17 | we'll call this class A, and we'll give it
one data member, and remember that data
| | 00:23 | member is private because we
haven't declared it otherwise.
| | 00:26 | And I'm going to type the word public
here, and you'll notice that Eclipse is
| | 00:30 | really nice about flush-lefting that
for us, and we'll go ahead and declare a
| | 00:34 | couple of public interface methods.
| | 00:37 | And these are what are called accessors,
these types of methods, because they're
| | 00:40 | going to be used to access
that private data member.
| | 00:44 | First one is setter, so this will set A,
so it returns void, and it takes a
| | 00:50 | const int a as its argument.
We'll just say ia = a;
| | 00:58 | and so that's a simple setter and all
that it does is it takes this argument and
| | 01:02 | use it to set the value of
the private data member ia.
| | 01:05 | So we'll go ahead and declare a getter.
| | 01:07 | Now this one will return an int, and
it'll be called getA, and it has no
| | 01:13 | argument, and it'll simply return ia like that.
| | 01:19 | And so it's a very simple setter and getter.
These are called accessor methods.
| | 01:22 | They're used for accessing private data
members and they're very common, and so
| | 01:27 | that's a very simple little class
for our experimenting with here.
| | 01:32 | Now we'll declare an object based on
that class, so we do that like that.
| | 01:37 | The capital A is the class type and the lowercase a
is now the object that's an instance of that class.
| | 01:44 | And we'll use our setter to set the
value. I'm going to give a value of say 47,
| | 01:50 | and then we'll use our getter to
retrieve the value, and we're going to use cout
| | 01:57 | to display it like that, and we'll
just compile and run this, and you'll see
| | 02:03 | that it prints up 47 exactly as we expected.
| | 02:07 | Now we can easily set and get
values from our simple class.
| | 02:12 | Now it's common object-oriented
practice, and it's considered best practice,
| | 02:16 | actually, to separate the
interface from the implementation.
| | 02:19 | This is done by declaring the member functions
in the class definition and defining them later.
| | 02:25 | So if I take these member functions,
and I just copy them and paste them down
| | 02:29 | here, I'm going to go ahead and
adjust these first so that they're proper
| | 02:34 | declarations and they're not definitions.
| | 02:36 | So I simply take out the code and the
curly braces and put in a semicolon.
| | 02:42 | Now they're definitions instead of declarations.
| | 02:45 | And then I'll take these, and in order
to make these actual implementations, I
| | 02:49 | need to declare that they're of this
type, that they're part of this class.
| | 02:53 | I do that by giving the class
name with two colons, like that.
| | 02:59 | Now this is actually proper code, and
I'm going to go ahead and format it a
| | 03:03 | little bit so that it's
formatted like normal functions.
| | 03:09 | So now what we have is we have our
class interface, which is the definition of
| | 03:13 | the class without the definitions of
the function members, and we have our
| | 03:18 | implementation which is the
function members by themselves.
| | 03:20 | Normally these would be in separate files.
| | 03:23 | The class definition would be in a
file called something like a.hpp and the
| | 03:30 | class implementation would be in a
file called something like a.cpp.
| | 03:35 | And then everything else would be in
other files, so it would be linked to the
| | 03:39 | object file after the compilation process.
| | 03:41 | But for our purposes, for the purposes
of teaching, it's really convenient to
| | 03:44 | have all these small
little examples in one file.
| | 03:46 | So just note that this is
not normally how it's done.
| | 03:50 | There's one other very important
detail here that you need to understand at
| | 03:54 | this point, and that's the concept of something
called const functions or const-safe functions.
| | 04:00 | So we're going to illustrate that by
creating another A object, and this one
| | 04:06 | we'll call b, and we'll
simply assign the first one to it.
| | 04:10 | So we now have an object b that's of
type A, and we have copied object a into b.
| | 04:17 | So it's got exactly the same data members.
| | 04:19 | So we would expect that we would be
able to do this and simply say b, and then
| | 04:26 | we would get the same value.
| | 04:27 | I'm going to go ahead and put a
string in here so we know which is which.
| | 04:32 | And when I compile and run this, you'll
see that we've got, a is 47 and b is 47.
| | 04:38 | Now if I take b, and I declare it as a
const object, like that, with the const
| | 04:43 | keyword, now you notice we
immediately get an error.
| | 04:47 | So the error message says
overload of 'endl', which is just weird, and
| | 04:52 | Invalid arguments ' Candidates are: int getA() '.
| | 04:55 | So the problem here is really with this,
Invalid arguments, and it's not a very
| | 05:01 | helpful error message.
| | 05:03 | If I save this and compile it, and we'll
see what comes out of the compiler--I'm
| | 05:07 | going to go ahead and click the
Run in Background button on that;
| | 05:10 | if you get that you'll do the same thing,
Errors exist in project. Continue launch? No.
| | 05:14 | Let's take a look at what the errors are here.
| | 05:18 | Here we get a slightly
more intelligible error,
| | 05:21 | passing 'const A' as 'this' argument of
'int A::getA()' discards qualifiers.
| | 05:27 | You'll see that discards qualifiers every
time you accidentally do something like this.
| | 05:31 | That's why I wanted to
show you that error message.
| | 05:34 | And the problem actually is that this getA
function member is not what we call const-safe.
| | 05:42 | So in other words, when the object
is declared as a const, we cannot use
| | 05:48 | function members that are not const-safe.
So what does const-safe mean?
| | 05:53 | Const-safe means that it's been declared as
const-safe like this, with the const keyword.
| | 06:00 | And of course, we need to do it also
up here where it's initially declared.
| | 06:06 | So when I do that, and I just hit
Save, that makes this function member
| | 06:10 | const-safe, and now I'll be able to
compile and run this, and it'll work just
| | 06:16 | fine, exactly as we expect, b is 47.
So what exactly does const-safe mean?
| | 06:22 | Const-safe means I guarantee that I
will not do anything in this function that
| | 06:28 | is not safe to do on a const object.
| | 06:32 | And for the most part, that means that
I won't change anything, and then if I
| | 06:35 | do change anything, I'm going to do it very
explicitly, and I'm going to use special keywords.
| | 06:40 | But for the most part, it really means
I'm not going to do anything that's not
| | 06:44 | const-safe in this function.
| | 06:45 | I'm not going to actually
change anything in this const object.
| | 06:50 | So the rule is a non-const object
may use any of the const-safe or not
| | 06:56 | const-safe methods in the class.
| | 07:00 | But a const object may only use
const-safe methods in the class.
| | 07:07 | In fact, it's possible to
declare two separate versions of this.
| | 07:10 | So I'm going to do this right now.
| | 07:13 | One of them const-safe and
one of them not const-safe.
| | 07:17 | And then I can come down here, and I
can duplicate this, and I can make the
| | 07:22 | duplicate not const-safe.
| | 07:25 | And just so you can tell which one is
being called, I'm just going to put out a
| | 07:30 | little message from each of them,
calling this the mutable getA because mutable
| | 07:33 | is another word that's
sometimes used for not const-safe.
| | 07:39 | And this one is the const getA.
| | 07:41 | Now because there are two versions, and
one of them is const-safe and one of them
| | 07:47 | is not, the mutable version of A--
which is this one here, the one that's not
| | 07:52 | declared as a const--that will
prefer the mutable version of getA.
| | 07:58 | And the const version of A, the one that's called b,
is actually only allowed to use the const version.
| | 08:04 | So we'll go we'll run this,
and you'll see that we get the mutable
| | 08:07 | getA for the first one, and this is
the const getA for the second one.
| | 08:11 | So the const function is called for
the const object, and the non-const or
| | 08:15 | mutable function is
called for non-const objects.
| | 08:18 | So you can remember this
simple rule of const functions.
| | 08:22 | Const-safe functions may always be called.
| | 08:25 | Non-const safe functions may
only be called by non-const objects.
| | 08:31 | So member functions are what make
object-oriented programming possible.
| | 08:35 | As we go through the rest of this
chapter, you'll see that most of the other
| | 08:38 | features of C++ objects are based on
the ability to create member functions.
| | 08:43 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Pointing to the current object with the *this pointer| 00:00 | Object member functions in C++ make use of the
keyword This to provide a pointer to the current object.
| | 00:06 | Let's take a look at how this works.
| | 00:10 | Make a working copy of class.cpp and
paste it into our Working project, and you
| | 00:16 | see we've our very simple class here.
I'll just go ahead and maximize this so
| | 00:21 | you can see the whole thing.
| | 00:22 | It has one data member i, and it has two public
function members which are setters and getters.
| | 00:27 | They are accessors for
setting and getting the value of i.
| | 00:31 | We declare an object of Class1.
| | 00:34 | We set its value, when we print out its
value, and when we run it, it looks like
| | 00:39 | this, value is 47, that's
exactly what we expect here.
| | 00:43 | So now we're going to go ahead and we're
just going to add a function member here.
| | 00:48 | We'll give it a void value,
and we'll call it lookAtThis.
| | 00:53 | And it will take one argument, and it
will be an int call i, and we'll just do
| | 00:59 | the implementation down here,
void Class1::lookAtThis( int i ), and we're just
| | 01:09 | going to print out the value of i
here, printf("i is %dn", i); like that.
| | 01:17 | Now we'll come down here, and we'll say object1.lookAtThis,
and we'll give it, say, a 9 like that.
| | 01:29 | And now when we Save this and Compile
and Run it, you'll see i is 9 and of
| | 01:35 | course, the value down
here in this getValue is 47.
| | 01:39 | This is an interesting result because
you'll notice that our class has a data
| | 01:45 | member called i and yet we've passed
an argument called i, and it printed out
| | 01:51 | the argument, it did not
print out the data member.
| | 01:53 | So that's kind of what we would expect.
| | 01:55 | The i from the local scope overrides the i
from the larger scope, from the class scope.
| | 02:01 | But what if we wanted to actually also be
able to access the i from the class scope?
| | 02:05 | We don't want to say, Class1::i because
that's the class, that's not the object.
| | 02:12 | What we really want is the
object i, and that's done like this.
| | 02:17 | So the This keyword actually gives
us a pointer to the current object.
| | 02:23 | And we can say here our object i is that, and so when
I run this, we have object i is 47 and value is 47.
| | 02:35 | So the This pointer can actually be really, really
handy, it can be handy in circumstances like this.
| | 02:41 | It can be handy when you're trying to do more complex
things to get out objects within your own object.
| | 02:48 | And it is actually a
pointer to the current object.
| | 02:52 | If I say printf, this is and give it a %p,
which is printf is for print out a
| | 03:00 | pointer, and then I also come down here,
and I say object1 is, and I give this
| | 03:10 | object1 or the address of, like that.
| | 03:14 | We'll need a semicolon in both of these
places in order for that to compile and run.
| | 03:20 | And so I will press the big green
Compile and Run button, and we see our
| | 03:26 | addresses that are printed out about
those two pointers are exactly the same.
| | 03:29 | So within the object, we're able to access a
pointer to the object with the This keyword.
| | 03:36 | So the This pointer is very
useful in some circumstances.
| | 03:39 | For example, when overloading an
assignment operator, you'll want to return a
| | 03:43 | reference to the current object so
that your assignments can be chained.
| | 03:46 | We'll see some examples of
this later in this chapter.
| | 03:49 | For now, let's delete the Working file and
run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using constructors and destructors| 00:00 | Constructors and destructors are special member
functions and serve a particular purpose.
| | 00:05 | There are several types of constructors
in C++ and one type of destructor.
| | 00:09 | Let's take a look at class.cpp for an example.
| | 00:12 | We'll copy this and paste it into our
Working project and open it up in the editor.
| | 00:17 | I'm just going to maximize
it so you can see it here.
| | 00:20 | Here is our very simple class, and
you'll notice that among other things it has
| | 00:23 | no constructors or destructors defined,
and so C++ in a case like this where you
| | 00:28 | don't provide any constructors or
destructors, it implicitly provides a default
| | 00:33 | constructor which is a constructor
that takes no arguments, and you'll notice
| | 00:36 | the way this is constructed in
line 15, there are no arguments.
| | 00:40 | And so the default constructor is the
one that's being called, and that's the
| | 00:43 | implicit default constructor
that's provided by C++.
| | 00:46 | There is also a Copy Constructor provided
and a Copy Operator provided and a destructor provided.
| | 00:53 | So let's go ahead and
run this for a second here.
| | 00:56 | We'll push the Compile and Run button,
and you see that value is 47, and that
| | 01:02 | happens on line 18 where the value is printed.
| | 01:04 | Go ahead and make a copy of that line
18, and I'm going to paste it in before
| | 01:08 | the setValue line and so now it looks like this.
I'm going to Save and Compile and Run.
| | 01:14 | And you'll notice that the default--
the implicit default constructor has
| | 01:18 | actually set the value of
our private data member to zero.
| | 01:22 | And what the implicit default
constructor does is it actually calls the default
| | 01:26 | constructor on any of the data members
in the class, and so in this case we had
| | 01:30 | 1, it's an int and the default
constructor on an int sets its value to zero.
| | 01:34 | So that's the Implicit Constructors
and Destructors. Let's go ahead and close
| | 01:38 | this, and we're going to delete our
class.cpp from our Working project there,
| | 01:43 | and run Clean, and now we're
going to really get into this.
| | 01:48 | Let's make a copy of constructors.cpp, and
I'm going to paste that into working here.
| | 01:53 | We're going to maximize that so we can see it.
I'm just going to page through real quick.
| | 01:58 | It's a bit long for the folks
who are typing along at home.
| | 02:01 | I'm just going to point out
a few things here to start.
| | 02:04 | You'll notice we have our class Animal,
and you'll notice it has a number of
| | 02:07 | constructors and a destructor defined
and even has a copy operator defined.
| | 02:11 | And we're going to get into all of
that in a moment, and then you notice the
| | 02:15 | Implementation section here where we have
actually provided the implementation for
| | 02:19 | all of these member functions, and
there is our operator overload and then down
| | 02:23 | at the bottom there there's a main
function which constructs a number of
| | 02:26 | different versions of this, and it
constructs them in different ways.
| | 02:30 | So a constructor looks like this.
| | 02:31 | Let's take a single or
default constructor on line 13.
| | 02:35 | The default constructor has no
arguments, and so it's the name of the class.
| | 02:38 | When the name of the class is the name
of the function that means it is a constructor.
| | 02:43 | So constructors are just the name of
the class as the function name and then
| | 02:47 | whatever arguments and
whatever implementation you have.
| | 02:49 | So in this case we have a default
constructor because it has no arguments.
| | 02:54 | So line 13 is the default
constructor, line 14 is the constructor with
| | 02:58 | arguments, and you'll notice that this constructor
has three arguments and they are all strings.
| | 03:03 | Line 16 has what's called a copy
constructor, because this constructor has as
| | 03:07 | its single argument
another object of the same type.
| | 03:11 | Line 17 is our copy operator,
and this is an operator overload.
| | 03:15 | It returns a reference to the object
itself, and it takes as its parameter a
| | 03:20 | reference to an object of the same type.
| | 03:22 | Line 18 is the destructor, and the
destructor is indicated by a tilde in front of
| | 03:26 | the function name and then the function
name after the tilde is exactly the same
| | 03:30 | as the object or the constructor.
| | 03:33 | And finally, we have a print method that
we're going to use for printing out these objects.
| | 03:37 | So let's take a look at the implementation
for the default constructor on line 22.
| | 03:42 | So this is a syntax that you
probably haven't seen before.
| | 03:45 | You notice we have this colon, and then
after the colon we have these things that
| | 03:49 | look like constructors or function
calls before the opening curly brace.
| | 03:55 | This is what's called the
constructor initializer list.
| | 03:59 | So the colon sets it apart, and then
you can actually initialize your data
| | 04:04 | members without ever actually
getting into the body of the function, and
| | 04:07 | whatever is here is actually
executed before the body of the function.
| | 04:11 | So you may actually not
even have a body of a function.
| | 04:14 | In this case we only have a body so
that we can print out this string.
| | 04:18 | So the way these initializers work is
you have the name of the object that's
| | 04:22 | being initialized--in this case it's
that string type--and then in parentheses
| | 04:25 | you have whatever value you're
going to be initializing it as.
| | 04:28 | This is actually the same syntax as if you
were going to call a constructor or an object.
| | 04:33 | If we come down here into the body of
our main, you'll see that we construct
| | 04:37 | this b object which is of type
const Animal, and we construct it with
| | 04:42 | parentheses and then
parameters inside the parentheses.
| | 04:45 | And so the same syntax is what's used
in the constructor initializer list,
| | 04:50 | and so they're separated by commas, and you
can initialize whatever you want up there.
| | 04:54 | And then in the body of the function
we just have this cout, and the purpose
| | 04:57 | of that is so that as we call each of these
constructors we have an idea what's happening.
| | 05:01 | We can kind of follow the flow.
| | 05:03 | It's really just for educational purposes.
You wouldn't put that in an actual constructor.
| | 05:07 | So moving along in line 26 we have the
constructor with arguments, and here we
| | 05:12 | have the arguments list, we have type,
name, and sound, and these are strings, and
| | 05:17 | we were simply initializing in our
initializer list those corresponding
| | 05:21 | variables in our data members.
| | 05:23 | We have the copy constructor starting at line 31.
| | 05:26 | This takes a reference to an
Animal object as its argument.
| | 05:30 | We print out a string that says this is the
copy constructor, and then we do the assignments.
| | 05:35 | We assign the data members from the
object being copied to the data members in
| | 05:39 | our own object, and you'll notice
here on line 35, we're prefixing this
| | 05:43 | clone_prefix, this is from our
constants up on lines 5 and 6.
| | 05:47 | The unknown constant on line 5 is
being used in our initializations on line 22,
| | 05:51 | and the clone_prefix constant is being used
in our copy constructor down there on line 35.
| | 05:58 | Then we have our destructor, and again, we just have
a string that says we're calling the destructor.
| | 06:03 | There isn't really anything
for the destructor to do here.
| | 06:05 | We have our print function down on line 44,
which simply prints out the name, the
| | 06:10 | type, and the sound of the animal.
| | 06:13 | And then on line 49 we're actually
overloading the assignment operator and the
| | 06:17 | reason that we're doing this it's something called
the Rule of Threes, and this is a C++ thing.
| | 06:23 | You might--you hear it referred to now and then.
| | 06:25 | The Rule of Three says that if you find
yourself needing to overload any of the
| | 06:29 | implicit methods that C++ normally
provides--the copy constructor, the destructor,
| | 06:34 | or the copy operator--if you find
yourself needing to overload any one of those,
| | 06:38 | you should probably think
about overloading all three.
| | 06:40 | And in fact, especially because we're
overloading the copy constructor, we want
| | 06:44 | to overload the assignment operator
so that you can see the distinction.
| | 06:48 | You can see when we run it.
| | 06:50 | A difference between what happens on
line 66 and what happens on line 69.
| | 06:54 | Line 66 is a copy constructor and
line 69 is an assignment operator.
| | 06:58 | So we'll be able to see what happens there.
So let's go ahead and run our code.
| | 07:02 | I'm going to press the big green
Compile and Run button here, and here we
| | 07:08 | have what goes on, and we're going to come
down here into main, and we'll see what happens.
| | 07:13 | In line 60 we construct an object with a
default constructor, and that's because
| | 07:17 | it has no arguments, it's just Animal a
like that, and so we'll notice our
| | 07:21 | default constructor up here on line 22,
it simply initializes our three
| | 07:27 | variables with the unknown constant
string, and there is our unknown constant
| | 07:31 | string up there has the
word unknown in it on line 5.
| | 07:35 | So our default constructor, and then
we call print, and we see it prints out
| | 07:40 | unknown the unknown says unknown.
| | 07:41 | So that's exactly what we expect to
have happen with or default constructor.
| | 07:45 | Next we call the constructor with
arguments with goat, bob, and baah, and so we
| | 07:50 | get the string constructor with
arguments, so we know that we're calling the
| | 07:53 | right constructor and the print
prints out, bob the goat says baah.
| | 07:57 | Then we call our copy constructor on
line 66, and we see we get the string copy
| | 08:02 | constructor on our console, and then
it says clone-bob the goat says baah.
| | 08:06 | Because our copy constructor is
copying object b as it constructs object c.
| | 08:12 | And so our copy constructor, you'll remember here--
let's go up and take a look at our copy constructor.
| | 08:17 | On line 35 it copies the name, but
it prefixes that clone_prefix and
| | 08:22 | clone_prefix again is up there on
line 6, and it says clone- and so we get
| | 08:28 | clone-bob the goat says baah.
| | 08:30 | And just to see the difference, on
line 69 we have the assignment operator.
| | 08:35 | We're assigning the value from c, which you
remember it says clone-bob the goat says baah.
| | 08:40 | We're copying that object into
a using the assignment operator.
| | 08:44 | And so if we look up in our assignment
operator, right there we see on line 53
| | 08:50 | it copies name with the clone_prefix
again, and so when we print it out on line
| | 08:54 | 70 we get, clone-clone-bob the goat says baah.
That's this one right here.
| | 09:00 | Now we're at the end of our function
and all of the destructors get called
| | 09:03 | because all these objects go out of
scope and so they all get automatically
| | 09:07 | destructed, and they get
destructed in reverse order.
| | 09:09 | So the first one to get destructed is c,
and remember c says clone-bob the goat.
| | 09:14 | Then b gets destructed which is just
bob the goat, because it doesn't have any
| | 09:18 | copy operations involved in it, and
then a gets destructed, and remember a was
| | 09:23 | assigned with the assignment operator,
and it got a copy of c, and it got
| | 09:27 | clone-clone-bob the goat.
And so that's our last destructor there.
| | 09:31 | So just one more thing that we need to
cover here, and I'm going to maximize
| | 09:35 | this so that we can see this.
| | 09:37 | You remember that C++ provides
implicit constructors, and for example, the
| | 09:40 | default constructor here--which I've
highlighted here on line 13--if I don't
| | 09:45 | define one C++ provides an implicit one.
| | 09:48 | If I want the object to disallow the
default constructor--in other words, coming
| | 09:52 | down here into main--and the way that
I've constructed the a object on line 60.
| | 09:57 | If I want that to be illegal, if I
want that to be disallowed, that's not a
| | 10:01 | valid use case for my class.
| | 10:04 | I can do that by simply taking this
default constructor and instead of declaring
| | 10:09 | it there in public, if I declare it
in private, now it cannot be called.
| | 10:13 | And if I do that of course, I need
to get rid of this because I have no
| | 10:17 | implementation for it, and I need to
provide it with an empty set of curly braces.
| | 10:22 | So now I have a default constructor,
I've defined my own default constructor.
| | 10:25 | I've overloaded the one that's provided implicitly,
but it's in private so it cannot be called.
| | 10:31 | It cannot be seen from the outside.
| | 10:33 | So if I try to compile this, I'll get
an error, and we'll need to go back out,
| | 10:38 | we'll need to minimize this
so we can see the errors here.
| | 10:41 | The error says 'Animal::Animal()' is private,
and so that simply disallows it.
| | 10:46 | It makes it so that if I try to do this I get
an error in my compilation, and I realize, oh!
| | 10:51 | I need to actually give that some parameters.
| | 10:53 | So you can overload your implicit
constructors in the private section to disallow them.
| | 10:58 | This was a lot, but it's
important to understand the constructors.
| | 11:01 | Constructors and destructors are
important parts of any C++ class.
| | 11:05 | It's always worth thinking carefully
about how your objects are constructed, and
| | 11:09 | crafting constructors and destructors
that handle all the necessary use cases.
| | 11:14 | So let's go ahead and delete the Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Exploring implicit vs. explicit constructor type conversions| 00:00 | When a constructor has only one parameter, it
can be used to provide implicit type conversion.
| | 00:06 | The explicit function
modifier prevents this behavior.
| | 00:10 | Let's take a look at how this works.
| | 00:12 | Make a copy of implicit-explicit.cpp
and paste it into our Working project and
| | 00:16 | open it up in our editor.
| | 00:18 | I'm going to maximize
this so that we can see it.
| | 00:21 | I'll just scroll through here briefly
for those who are typing along at home.
| | 00:25 | So this is a partial class, this
is hypothetically the beginning of
| | 00:29 | the roll-your-own-string class, and it's
getting a length, a string length parameter.
| | 00:35 | And really that's all the
class does at this point.
| | 00:37 | It just has the one data member;
| | 00:39 | its size data member, and it's of type
size_t, and it's going to be eventually
| | 00:44 | used as some kind of a string thing.
And so we have two constructors.
| | 00:47 | We have a constructor from a size_t
which gets automatically converted from
| | 00:51 | int, and we have a constructor from a c-string
which will take the size from c-string.
| | 00:55 | And then we have this little getter,
this little accessor in Line 11, it'll
| | 01:00 | return the size so that
we can see what's going on.
| | 01:03 | So it's really just for experimental purposes.
| | 01:05 | So the first constructor is
implemented beginning on Line 14, and you see it
| | 01:10 | says it takes a size_t variable, and
it checks to make sure that it's not
| | 01:14 | greater than maxlen, and it assigns it to size.
| | 01:17 | And then you can see the constructor
beginning on Line 19 takes a string and
| | 01:20 | finds the length of that
string, and it uses that for size.
| | 01:24 | And then we have our little getter on Line 30 and then
starting on Line 34, we have our little test bed.
| | 01:29 | So there's two things in
here, in the main function
| | 01:32 | we construct an object using s =,
and I assigned a character by mistake.
| | 01:36 | It was supposed to be a string of one
length, but I assigned a character so
| | 01:39 | that's going to get converted into the
size_t, and it'll take the value of that.
| | 01:42 | And then you see the other implicit
conversion that happens is in the function call.
| | 01:46 | You notice that the function is
declared as requiring a BWSize object and
| | 01:51 | instead I'm just passing it this character.
| | 01:53 | Again, by mistake, it is supposed to
be a string, but it's a character, and
| | 01:57 | that's getting automatically converted also
into this unsigned integer that is size_t.
| | 02:01 | And so we have these implicit
conversions going along, and in both cases they're
| | 02:04 | really something that we didn't intend,
but they're happening by accident.
| | 02:07 | And you'll notice that when I compile
and run this that it actually works.
| | 02:11 | It doesn't do what I intended.
| | 02:13 | Instead of giving me that one length
that I might have meant, this character is
| | 02:16 | getting converted to the integer value
120, and it's getting assigned to size.
| | 02:20 | So we can make this not happen by using
the explicit keyword. So both of these
| | 02:26 | syntaxes are actually
designed to do implicit conversions.
| | 02:29 | When you initialize an object with the
equal sign instead of the parentheses,
| | 02:34 | it's designed to do an implicit conversion.
| | 02:36 | And when you initialize an object by
passing something into a function like
| | 02:40 | this, it's also doing an implicit
conversion because the function is
| | 02:44 | requesting a BWSize object, and I'm
actually giving it something else, and so
| | 02:48 | it tries to do a conversion.
| | 02:50 | So we can prevent these implicit
conversions by using the explicit keyword.
| | 02:53 | So if I just type explicit here and
here, now none of this will work anymore,
| | 02:59 | and we won't actually be able to compile.
| | 03:01 | If I try to compile this, I get
errors and the errors look like this:
| | 03:05 | conversion from 'char' to non-scalar
type 'BWSize' requested, invalid
| | 03:10 | initialization reference 'const'
from expression type 'char'.
| | 03:13 | So we're having problems here.
| | 03:15 | There's our conversion problem, there's
this weird initialization of type from
| | 03:20 | char that's also a conversion problem, and here
we have passing argument 1, that problem there.
| | 03:27 | So this no longer works
because we have explicit.
| | 03:29 | Once we have explicit, we
have to actually match things.
| | 03:32 | In fact, let's comment out the second
one and just start with the first one.
| | 03:35 | So I'll comment that out. And then this one
here, let's just try to give it a number, 125.
| | 03:40 | And if I save that and try to compile
it, we still have an error because it's
| | 03:45 | still trying to do an
implicit conversion for two reasons.
| | 03:47 | One is that I'm using this syntax
with the equal sign, and the other is
| | 03:52 | that that's an int; it's not a size_t.
| | 03:54 | So I can make this a size_t and try
that, save that and compile it, I get the
| | 03:59 | little--and just hit Run
in Background if you get this.
| | 04:02 | And you see we still have an error
because it's still trying to do an implicit
| | 04:06 | conversion because this syntax here
is actually the syntax of the copy
| | 04:11 | constructor, and that's not the
kind of a constructor we have.
| | 04:14 | We have the parameterized constructor.
| | 04:16 | So I need to actually even do
this in order for this to work.
| | 04:19 | So now I save this and run it, and
now it works because I'm calling the
| | 04:25 | constructor that I intended, and I'm
calling with the type that I intended.
| | 04:28 | That's a little bit
inconvenient to have it be a size_t.
| | 04:31 | If I want this to be an int, I can come
up here and instead of the size_t, I can
| | 04:36 | say const unsigned int.
| | 04:40 | And I'll come down here into the
implementation and do the same thing, const
| | 04:45 | unsigned int, and now I should be able to
initialize it like that, and there we have it.
| | 04:53 | Now with func, let's try to get it
to use this other constructor here.
| | 04:58 | Obviously, if I just uncomment this
and put in a string instead of that
| | 05:02 | character, we're not
going to expect that to run.
| | 05:05 | Why? Because we're still
trying to do an implicit conversion.
| | 05:08 | This function is requesting a BWSize
object, and I'm passing it a string.
| | 05:13 | And so if I compile this, I get errors,
and the error looks something like this:
| | 05:18 | invalid arguments, invalid initialization of
reference type, and here we have passing argument.
| | 05:25 | So it really needs for me to pass it a
BWSize object, so I need to do it like this.
| | 05:30 | And what this will do is this will
construct a temporary object and pass it.
| | 05:34 | So this constructs a temporary object of
BWSize type, and it initializes it with
| | 05:38 | that constant character string, and so
if I compile this and run it, we get a
| | 05:42 | size of 1, which is exactly right.
| | 05:44 | And so if I give this five of them and
compile and run that, we'll get a size of 5.
| | 05:51 | So here we see that by using the
explicit keyword, we have prevented implicit
| | 05:55 | conversions in our constructors.
| | 05:57 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Overloading operators with member functions| 00:00 | Operator overloading is not unique in C++.
| | 00:03 | In fact, it was one of the original
concepts borrowed from ALGOL for C++, but
| | 00:08 | how C++ does it is fairly
unique and extremely powerful.
| | 00:13 | There are two distinct ways
to overload operators in C++,
| | 00:16 | one with member functions as part of
a class definition, and the other as
| | 00:20 | separate non-member functions.
| | 00:22 | In this movie, we'll discuss operator overloading
with member functions in your class definitions.
| | 00:26 | We'll discuss the non-member
functions in another movie.
| | 00:30 | Let's make a working copy of rational.cpp,
and we'll paste that into our working
| | 00:36 | project and open it up and maximize it here.
| | 00:39 | I'm just going to page through this
briefly for those who are typing along at home.
| | 00:43 | So here we have a class that
implements a simple rational number, that is a
| | 00:48 | number that has a numerator and a
denominator, and we want to be able to operate
| | 00:52 | on these rational numbers, we want to be able to
use the four-function arithmetic operators on them.
| | 00:56 | And so we have our member
functions defined to do that.
| | 01:00 | So first, we have a couple of constructors.
| | 01:01 | We have one that constructs with the
numerator and denominator, and that one is
| | 01:05 | entirely implemented here
in the class definition.
| | 01:08 | So this separates out the initializer
list, and then we have the initializer
| | 01:11 | list right here that initializes n as
the numerator and d as the denominator,
| | 01:17 | and we have an empty function body.
| | 01:19 | So this fits really nicely here.
| | 01:20 | Sometimes I'll break my own rule, and
I'll have some implementation in the class
| | 01:24 | definition if it's that simple,
and it fits that concisely.
| | 01:27 | And again, with the copy
constructor we did the same thing.
| | 01:31 | And there's a destructor, and the
destructor is defined here, but it's
| | 01:34 | actually implemented down below, and we have
a couple of getters for numerator and denominator.
| | 01:39 | Again, since they're so simple, I
went ahead and implemented them here.
| | 01:42 | And then we have five operator overloads.
| | 01:45 | We have the copy operator, and we have the
plus, minus, multiply, and divide operators.
| | 01:51 | So let's take a look at these implementations.
Here's the copy operator.
| | 01:55 | The copy operator returns a reference
to itself, that is to its own object, and
| | 02:01 | it does that using the this pointer.
| | 02:03 | It also uses the this pointer to compare
the address of the object that's being
| | 02:08 | passed to it to make sure they're not the same.
If they are the same, it does nothing.
| | 02:12 | If not, it prints out the word
assignment so that we know that it happened, and
| | 02:16 | it copies over the data members.
| | 02:18 | Our 'for' function arithmetic
operator overloads are incredibly simple.
| | 02:22 | We have on Line 29 the plus operator,
on Line 33 the minus operator, on Line 37
| | 02:28 | the multiply operator, and on
Line 41 the division operator.
| | 02:32 | These are all defined as being const-
safe because they don't actually have to
| | 02:37 | modify anything in the object and they
use very simple formulas for doing the
| | 02:42 | multiplication, division, addition,
and subtraction of the rational objects.
| | 02:47 | Then on Line 45 is the destructor, and
it simply prints out that we're calling
| | 02:52 | the destructor so that we know that it happened.
| | 02:54 | On line 50 is something else again,
and this is simply a convenience function
| | 02:59 | for making these objects
work with the outstream.
| | 03:03 | This makes it possible to do what
we're doing on Line 71 through 74, which is
| | 03:08 | actually printing out these objects using cout.
| | 03:12 | And in fact, this function beginning
on Line 50 is an example of an operator
| | 03:17 | overload as a non-member function, so we'll cover
the details of how that works in our next movie.
| | 03:24 | For now, let's go ahead and bring this
back down to size and compile and run
| | 03:28 | and see how this works.
| | 03:31 | So starting at the top, we're
constructing object a, and we're giving it a value
| | 03:36 | simply of 7, and it responds by saying a is: 7/1.
So let's see how this is working here.
| | 03:44 | You'll notice the first constructor
listed here on Line 8, it takes two
| | 03:49 | arguments, a numerator and a denominator,
and you'll notice that these have default values.
| | 03:54 | So this syntax here where it says
int numerator = 0, that gives it a default value.
| | 03:59 | If I don't pass it a numerator, then it'll
assign the value 0, and it'll use that instead.
| | 04:04 | And so what I've done here, you'll
notice that the denominator default is 1, and
| | 04:09 | I constructed it with simply a 7, and
so it presumed the one because rational
| | 04:15 | number that's equal to the integer 7
would be 7/1. Rational b I initialized with
| | 04:20 | 5/3, and again, we see that
in our results down here, b is: 5/3.
| | 04:24 | We use the copy constructor for c and
so that gives it also the value of the b.
| | 04:31 | There on Line 61, c = b so that is the
copy constructor, and it gives c the same
| | 04:36 | value as b, 5/3, and we use the default
constructor for d which makes it 0 over
| | 04:42 | 1, which is a rational number that's equal to 0.
| | 04:45 | Of course, you can't have a
denominator of 0 because that's illegal.
| | 04:48 | You can't divide by 0.
| | 04:50 | On Line 65 we then assign a value
to d with the assignment operator.
| | 04:56 | And so we get the word assignment here,
I'm going to scroll down, and that's
| | 05:01 | happening there because of Line 65, and
if we come up and look at our definition
| | 05:05 | of the assignment operator there on
Line 20, we see it prints out the word
| | 05:09 | assignment when it does that assignment.
| | 05:11 | In Line 67, we assign a reference
and so e becomes a reference to d, and
| | 05:17 | this doesn't call any of the constructors
because we're not constructing a new object.
| | 05:21 | And then on Line 68, we try to assign e
back to d, but that doesn't work because
| | 05:27 | it's an assignment to self.
| | 05:29 | And so we just get this next line e because
nothing happened in those other lines in our object.
| | 05:35 | Now starting on Line 71, we
start to get these strings.
| | 05:38 | We'll go ahead and scroll
down so you can see those.
| | 05:41 | On Line 71, we are adding a to b and so
a is 7/1 and b is 5/3 and the result is 26/3.
| | 05:48 | But you'll notice that then
there's a destructor for the object that has 26/3.
| | 05:53 | Why is this happening?
| | 05:56 | Well, what actually happens in this
line here, a + b, let's go take a look
| | 06:01 | at our plus operator, and we see
that our plus operator constructs a
| | 06:05 | temporary rational object.
| | 06:07 | This here is the class Rational and
inside of these parentheses is the
| | 06:13 | initialization of a temporary object.
| | 06:15 | And so we have a numerator here, and we
have a denominator here, and we return
| | 06:20 | that temporary object, and once it's
used, it gets destroyed because we're not
| | 06:24 | really assigning it to
anything that's going to keep it.
| | 06:26 | So at the end of this expression, we
take that value, and we pass it on to cout,
| | 06:32 | and when cout is all done,
that object gets destroyed.
| | 06:35 | And so this is the cout line,
and there's the destructor.
| | 06:38 | So the same thing happens for each of these.
| | 06:40 | Here's the subtraction, this is
multiplication, and so that's Line 72 and
| | 06:46 | 73, and then here's the division on Line 74,
and there's that object getting destroyed.
| | 06:52 | And then we're at the end of our main
and so all four of these objects, a, b, c,
| | 06:57 | and d, get destroyed in reverse order.
| | 06:59 | And you'll notice that e doesn't need
to be destroyed because e is simply a
| | 07:03 | reference, so it doesn't create any new object.
| | 07:06 | Let's take another quick
look at the assignment operator.
| | 07:09 | The assignment operator
is a bit of a special case.
| | 07:12 | Because you need to be able to chain assignment;
| | 07:14 | in other words, you need to be able to
say a = b = c = d, it actually needs to
| | 07:19 | return a reference to itself.
| | 07:22 | So that's what the return what's
pointed out by this statement does.
| | 07:26 | And then the type itself of the
operator function is the rational reference.
| | 07:32 | Also notice the test for assignment to
self, this is very common, and you should
| | 07:35 | do this every time you
create an assignment operator.
| | 07:39 | Also you'll notice that our four-function
arithmetic operators do not return references;
| | 07:43 | they return actual objects.
| | 07:45 | That is necessary because the
results of the expression should not return
| | 07:48 | a reference, because you wouldn't want to be
able to modify the results of an expression.
| | 07:52 | So it actually returns an object,
and in many cases, that object gets
| | 07:56 | immediately destroyed after it's used.
| | 07:58 | Operator overloading is a
fundamental part of C++.
| | 08:02 | It's as easy to do as defining a class method.
| | 08:04 | We'll look at some reasons to use
non-member functions for operator
| | 08:07 | overloading in our next movie.
| | 08:09 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Overloading operators with non-member functions| 00:00 | Operator overloading is fundamental to C++.
| | 00:03 | It's often accomplished with
member functions defined in a class.
| | 00:07 | In this movie, we'll look at why and
how you may sometimes use non-member
| | 00:11 | functions for operator overloading.
| | 00:13 | Let's make a working copy of rational.cpp,
copy that and paste it into our
| | 00:18 | Working project and open it up.
| | 00:19 | I am going to maximize this and scroll through it real
briefly for those who are typing along at home.
| | 00:24 | So what we have here is our Rational
number class that we constructed for the
| | 00:30 | movie on operator overloading as member
functions, and it has operator overloads
| | 00:35 | for the basic four function arithmetic:
| | 00:37 | addition, subtraction, multiplication, and
division there on lines 14 through 17.
| | 00:42 | And we'll notice if we go ahead
and run this that it works just fine.
| | 00:47 | Come down here to our testing section,
we'll see that we test these four
| | 00:51 | operators there and these
couts, and there are our results.
| | 00:55 | Now there is one important circumstance
where this technique just doesn't work,
| | 01:00 | and we are going to go ahead and make
a copy of our cout line where we do the
| | 01:05 | addition, and I am going to
change this to a + 14 instead of a + b.
| | 01:11 | And if I save that and run it, you'll
notice that that works exactly as expected.
| | 01:15 | Here we have our line 7/1 + 14 = 21/1, and that's
exactly what we would expect the result to be.
| | 01:23 | And the reason this works is if we come
up here to our operator overload for the
| | 01:28 | addition, you notice that the right-
hand side is expecting a rational object.
| | 01:33 | And our rational object has a
constructor that allows a type conversion, because
| | 01:38 | it accepts the numerator, and it has a
default value for the denominator, and
| | 01:42 | you'll remember if a constructor will allow just
one operand, then it will try to do a type conversion.
| | 01:49 | And so this is actually working because we
accept that one integer as our constructor.
| | 01:55 | So this is just using the type
conversion that's built into the constructor.
| | 01:59 | And in fact, what it does is when
it gets called for this plus operator
| | 02:04 | function, and it's expecting this
Rational object, it actually creates a
| | 02:09 | temporary Rational object and uses it
in the expression and then discards it.
| | 02:14 | And so you can see the destructor
here, right there is 14/1 destructor.
| | 02:18 | That's that temporary object getting destroyed.
So this is working beautifully.
| | 02:22 | Let's see what happens if we
try it the other way around.
| | 02:25 | If instead of a + 14, I try a 14 + a.
| | 02:30 | And I'll go, and I'll switch these
around just for clarity, and I'll save that,
| | 02:36 | and I'll compile and run it, and you
see we get a very long cascade of errors.
| | 02:41 | Look, it finally ended.
| | 02:43 | And if you were to read through all of
those and actually understand it, which I
| | 02:46 | don't recommend that you try to do
because it's a long cascade of errors, you
| | 02:50 | would find that the reason this isn't
working is because 14 is not a rational
| | 02:56 | object, 14 is a literal integer object,
and 14 does not have a plus operator
| | 03:04 | that will accept a rational object.
| | 03:06 | So the reason the other one worked is
because the left-hand side was the object.
| | 03:10 | The left-hand side of our overloaded
operator is the object itself, and that's
| | 03:15 | because it's an overloaded object in our class.
| | 03:19 | So, when you overload an operator in a
class, it expects the left-hand side to
| | 03:23 | be the class itself, and that's
how it knows what functional to call.
| | 03:27 | So the solution is to move the
operator overload out of the class.
| | 03:31 | Let's see how that's done.
| | 03:32 | We'll start by commenting this out
inside the class definition, and then we'll
| | 03:37 | come down here to our operator itself.
| | 03:39 | I am just going to move this down, cut
and paste, move it down to the end of our
| | 03:44 | class here, and we'll start
fixing it up so that it works.
| | 03:49 | We are going to take the Rational
class designator out of there, and we are
| | 03:53 | going to take this const designator out
of there, because that doesn't work if
| | 03:57 | it's not part of the class anymore.
| | 03:58 | And now what we need to do is we need to--
I am going to go ahead and maximize this.
| | 04:03 | Now we need to have a left-hand
side that's also a Rational object.
| | 04:07 | So I am going to come over here, I want to say
const Rational left-hand side and put in a comma.
| | 04:12 | Now the problem is that here we're
depending on having access to the private
| | 04:17 | member variables, and we
don't have that anymore.
| | 04:19 | So all of these places of in need to
become numerator and all of these places of _d
| | 04:24 | need to become denominator.
| | 04:26 | And we also need to have for the ones
that don't specify right-hand side, those
| | 04:30 | need to be left-hand side.
| | 04:31 | So let's start by putting those in.
Left-hand side dot.
| | 04:34 | And obviously, those aren't available,
but we'll fix that up in a moment.
| | 04:39 | So all the places where it has just a bare
one, which is really just these two places--
| | 04:44 | oh, there's one more here.
| | 04:46 | So now we have left-hand side and
right-hand side in all of the places we need.
| | 04:49 | This is going to get long, so I am
going to put this on a line by itself.
| | 04:54 | Now all the places with an _n are going
to get the numerator accessor, there is
| | 04:58 | numerator, and there's numerator.
| | 05:00 | Now all the places with an _d are going
to get the denominator accessor, there.
| | 05:06 | And now we have successfully moved this
operator outside of the function, and we
| | 05:11 | have an operator overload that takes a
rational number for both its left-hand
| | 05:15 | side and its right-hand side,
using our Rational class.
| | 05:19 | So this allows the compiler to
actually convert our integer constant to a
| | 05:23 | rational, because of our implicit
constructor, and now if we come down here, and
| | 05:27 | I am just going to minimize
this again so that we can run it.
| | 05:31 | And we have, this didn't work the last
time, I am going to save that and compile
| | 05:35 | it, and you see that now it works just fine.
14 + 7/1 = 21/1, right?
| | 05:43 | And there we have again our
destructor for that temporary object that got
| | 05:47 | created by the implicit conversion for
the left-hand side of our overloaded operator.
| | 05:53 | So there are definite circumstances
where you want to use non-member functions
| | 05:56 | for your operator overloads.
And C++ supports this as well.
| | 06:00 | In a nutshell, whenever you have a
constructor that allows implicit conversions,
| | 06:04 | you want to think about
non-member overload functions.
| | 06:07 | These functions should still
go in your implementation file.
| | 06:10 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using conversion operators| 00:00 | One final type of operator overload that's
worth understanding is the conversion operator.
| | 00:05 | Sometimes called a conversion function,
you can think of this like you are
| | 00:08 | overloading a cast operator for
casting your class to another type.
| | 00:13 | Let's take a look at an example.
| | 00:14 | We'll open our rational.cpp again,
copy that and paste it into Working.
| | 00:19 | I am going to come down here to the
bottom--let's go ahead and maximize this and
| | 00:24 | page through it briefly for the
people who are typing along at home.
| | 00:30 | I'm going to come down here at the end,
and I'm just going to add something.
| | 00:34 | Let's declare a string, and I'm going to
concatenate one of our rational numbers
| | 00:39 | to the end of that string
and then cout with it.
| | 00:44 | So what we would expect to have happen
assuming that we had this functionality
| | 00:48 | supported is that it would print out
Rational as a string, and then it would
| | 00:53 | print out the value of b in
numerator over denominator notation.
| | 00:57 | Of course, we haven't built the function of
for this yet, so we don't expect it to work.
| | 01:02 | But let's go ahead and compile and run
and see what happens, and there we get
| | 01:06 | a long cascade of errors for that.
And it basically says no match for
| | 01:10 | 'operator +=' in 's += b'.
| | 01:14 | So, the way we get this supported is
not by adding an operator to string,
| | 01:19 | because well that won't work, but
rather by allowing a cast of our Rational
| | 01:24 | class to a string, and we do this by
adding a conversion operator to convert
| | 01:29 | it to class string.
So here's what that looks like.
| | 01:32 | We say operator standard string,
and we make it const safe.
| | 01:37 | Now we come on down here, and we'll
come down to the end of our class, and we
| | 01:42 | will implement it like this.
| | 01:45 | We have to tell it that this function is
in the Rational class, and then we give
| | 01:50 | it the body of our function like this.
| | 01:51 | We're going to declare a
constant for the size of our string.
| | 01:55 | I am doing that because I'm
actually going to use a c-string for this.
| | 01:59 | I like this solution because it tends
to be faster and use less resources than
| | 02:04 | the alternative which would
be to use a string string.
| | 02:07 | So that takes a snprintf function
which does a printf type formatting into a
| | 02:13 | string with a maximum length, and it
takes our numerator and denominator
| | 02:18 | values and converts them into ints
and prints them out like that, and it
| | 02:22 | prints them into the string, and then
we can return the string as an operand
| | 02:25 | to a string class constructor.
| | 02:27 | So it's taking a c-string and then
converting it to a string class and returning that.
| | 02:32 | So now we have our operator overload
for this cast of string or our conversion
| | 02:38 | operator, and we've declared it in our class
up here on line 18, and we're using it down here.
| | 02:44 | So let's save and compile and run, and
there we have it, Rational as a string: 5/3.
| | 02:50 | So you can apply this same
technique to cast your class to any type.
| | 02:55 | The conversion operator overload is a
very useful technique that allows you
| | 02:59 | to use your class as a first-class type,
fully controlling how it is cast to other types.
| | 03:04 | So let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Creating function objects| 00:00 | By overloading the function operator, you can create
a class that operates as if it were a function.
| | 00:05 | This pattern is sometimes called a functor.
| | 00:08 | This can be a handy technique for
circumstances where you need to keep state or
| | 00:12 | other context information
with your function calls.
| | 00:15 | Let's make a working copy of
function-object.cpp and paste it into the
| | 00:21 | Working project, and we'll open
it up here in our editor.
| | 00:24 | I'll maximize it so that
you can see the whole thing.
| | 00:28 | So we have here is a very simple class
that overloads the function operator.
| | 00:32 | There you see on line nine, operator (),
that overloads the function operator.
| | 00:38 | And so when we construct this
object--like on line 13 we have a version
| | 00:42 | that multiplies by times4, on line 14 we have
have a version that MultBy times10, and
| | 00:48 | on line 15 we have a version
that MultBy times15.
| | 00:53 | So the object is constructed with an
argument that becomes the multiplier
| | 00:58 | and gets stored in the private data member on
line 6 called mult, which is the multiplier.
| | 01:05 | Whenever the function operator is
called it returns whatever argument is passed
| | 01:09 | multiplied by the multiplier.
| | 01:11 | So we see on line 16 through 21 that
unlike a function, we can actually use
| | 01:17 | different versions of this functor and
have several versions of it instantiated
| | 01:21 | at the same time to do different things.
| | 01:23 | So let's go ahead and Compile and Run
this, and we see that we have the times4
| | 01:30 | version, the times10 version, the times15 version,
and they are all doing what they are supposed to do.
| | 01:36 | The function operator is a handy way
to create an object that works like
| | 01:39 | a function yet has the ability to keep state
and other information between function calls.
| | 01:43 | We'll see some more practical examples of this when
we discuss algorithms in the standard template library.
| | 01:48 | Now let's delete the Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Creating and destroying objects with the new and delete operators| 00:00 | The New and Delete operators were
covered in the chapter on operators;
| | 00:03 | they are used to allocate memory in C++.
| | 00:07 | Let's make a working copy of new-delete.cpp.
We'll paste that into our Working
| | 00:13 | Project and open it up here.
| | 00:14 | We'll go ahead and maximize this
so that you can see the whole file.
| | 00:20 | It's worth noting here on line 28 that Eclipse is
giving me an error with the Null Pointer keyword.
| | 00:26 | This is a new keyword in C++.
| | 00:29 | The problem is is that with this new
version of GCC, null has been removed, the
| | 00:36 | old NULL macro has actually been
removed from the iostream header.
| | 00:42 | And so this won't work.
| | 00:44 | There are a number of workarounds.
We could just use a void* pointer, and
| | 00:48 | that'll work fine, or we can say if(!a),
and it just gets promoted to a bool,
| | 00:54 | and that works just fine.
| | 00:57 | Really the correct form here is to
use the new nullptr keyword, and Eclipse
| | 01:01 | doesn't know about it, but it compiles and
runs just fine, so that error we can safely ignore.
| | 01:06 | In the error if I hover over it here, it
just says Symbol could not be resolved.
| | 01:12 | So here we have a simple class, it's
got three data members that are integers
| | 01:16 | and our constructor that are in line 17
simply constructs them with 0, 1, 2,
| | 01:21 | and 3 as the default constructor, or if
we pass it an argument it will start with
| | 01:26 | that integer number and initialize them
with that number +1 and +2. We also have
| | 01:32 | defined a destructor and the destructor
just prints out a message that says
| | 01:37 | a destructor was called, and of course,
the constructor also prints out a message
| | 01:40 | that the constructor has been called.
| | 01:41 | So it's a very simple class. And down
here on line 27, we're allocating space for
| | 01:47 | one of these using the new operator.
| | 01:49 | The new operator of course
returns a pointer to this new object.
| | 01:52 | The nothrow parameter to the new
operator simply tells it not to throw
| | 01:56 | exceptions if it fails.
| | 01:58 | And then the new operator takes the
name of the class that it's allocating, and
| | 02:02 | it allocates space for that class,
and it calls the constructor.
| | 02:06 | In this case it's calling the default
constructor because we're not passing it a parameter.
| | 02:10 | And then down on line 33, we destroyed
the object that we've created by passing
| | 02:15 | the pointer that was created
by new to the delete operator.
| | 02:19 | And so let's go ahead and Run this.
| | 02:22 | Press the Compile and Run button there,
and you see the message, allocating
| | 02:26 | space for one A object that comes
from line 26, and then we actually
| | 02:30 | allocate space for an object, and it
gets constructed on line 27 and so we
| | 02:35 | see A constructor called.
| | 02:37 | It didn't fail, so we're not getting our error.
| | 02:39 | And on line 32, we're simply using the
accessors a, b, and c to print out the
| | 02:44 | value so we can see that we actually
have successfully created an object.
| | 02:47 | You notice that we're using the pointer
member dereference operators there for
| | 02:51 | a, b, and c right there on line 32,
and then we destroy the object with the
| | 02:55 | delete operator passing it the
pointer that was created in line 27.
| | 03:00 | And we can see A destructor called
and space for A object deleted.
| | 03:04 | If you want to, you can pass
arguments to the constructorl right here.
| | 03:08 | So we'll pass it a 5, and we'll Compile and Run.
| | 03:12 | We see now it's printing out 5, 6, and 7,
or you can allocate space for an array
| | 03:18 | instead of just allocating one.
| | 03:20 | So I can say 5 in brackets here, and that
will allocate space for an array of five objects.
| | 03:27 | If I do that I need to change the form
of delete to match, and I need to give
| | 03:31 | it empty brackets there, and it'll know how
many objects were created by this pointer.
| | 03:37 | So you have to make sure that you
save your pointer to pass to delete.
| | 03:41 | So now we're allocating space for five of these.
| | 03:43 | It will still say one because
I'm not going to change that.
| | 03:46 | And you'll see that we get five constructors
called, and five destructors called.
| | 03:51 | And in fact, if I want to I can
call printf on all five of these.
| | 04:00 | We'll go ahead and just dereference with the I,
rather than using this pointer operator.
| | 04:06 | That looks like that, and then when I
compile and run this you'll see we're able
| | 04:14 | to see all five of those.
| | 04:16 | When you're using new to create an
array, you cannot pass arguments to the
| | 04:20 | constructor, so it will
always use the default constructor.
| | 04:23 | And you always need to remember to use
the array form of delete to correspond.
| | 04:29 | The new operator is used for
allocating space for objects in C++.
| | 04:34 | Every object allocated with new must
be destroyed with delete, otherwise your
| | 04:38 | program will leak memory.
| | 04:40 | For more details, see the New and
Delete operators in the chapter on operators.
| | 04:45 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Reporting errors with exceptions| 00:00 | In C++, exceptions are used to report
errors, especially in circumstances where
| | 00:06 | errors cannot be reported locally.
| | 00:07 | Let's take a working copy of
exceptions.cpp from our Chap08 folder in our
| | 00:12 | exercise files, and we'll go ahead and paste
this in our Working project and open it up.
| | 00:17 | I am going to maximize this
so we can see the whole thing.
| | 00:20 | I'm just going to take a moment and page through
this for the folks who are typing along at home.
| | 00:28 | This file is based upon the constructor's
example from earlier in this chapter.
| | 00:33 | The C++ language has
complete support for exceptions.
| | 00:36 | For our purposes, this movie
is just a quick introduction.
| | 00:40 | In this case we want to do some error
checking in a constructor, and exceptions
| | 00:44 | make that really easy.
| | 00:45 | So let's start at the bottom, and you'll
see that we're constructing this object
| | 00:50 | inside of what's called a try block.
| | 00:52 | So on line 72 we'll use the keyword
try, and that's followed by opening and
| | 00:57 | closing curly braces with code in
between, and everything inside of that block
| | 01:03 | will be executed in this try block, and
so if any exceptions happen during that
| | 01:08 | block, then the catch
block is immediately called.
| | 01:11 | And the catch block here has an
argument which is the exception type, it's a
| | 01:17 | reference to an exception object, and
we'll see what that means in a minute, and
| | 01:21 | it simply outputs a message to
standard error using cerr, and it uses that
| | 01:27 | exception object, and it calls the
method on that exception object called what,
| | 01:31 | and that will have a description--a
human readable description, a string--to
| | 01:36 | describe the error that happened.
| | 01:38 | Up here at the top, I have a class
that's based upon the exception object, and
| | 01:42 | this is a very, very common way to do this.
| | 01:45 | My class is called E, the capital E, and
it disallows the default constructor on
| | 01:51 | line 11 by declaring it in the private
scope, and in the public scope it has a
| | 01:56 | constructor that takes one argument a
c-string, and it also has a method called
| | 02:01 | what, which is overloading the what
method in the exception base class--and again,
| | 02:06 | this is a very common way to do this.
| | 02:08 | So there is a couple of things
here that you might not recognize.
| | 02:11 | On line 13 in the constructor, you
see it says throw with an empty pair of
| | 02:16 | parentheses before its initializer
list, and what this syntax means is it's
| | 02:22 | specifying what exceptions are allowed
to be thrown from inside this function,
| | 02:27 | and that list is empty and so it's not
allowing any exceptions to be thrown from
| | 02:31 | inside that function, and that's
actually pretty important in the exception
| | 02:34 | class itself that the exception class
doesn't throw any exceptions, because then
| | 02:39 | it could get called recursively,
and it could create more problems.
| | 02:42 | And so we've done the same thing in the
what method, and you'll notice that it's
| | 02:46 | also declared as a const safe method,
and it simply returns the message.
| | 02:50 | So this is a very, very simple way to
derive a class based on the exception
| | 02:55 | class, and you can take this exact code and
use it to great benefit in your own programs.
| | 03:02 | This is pretty much the way that I do
exceptions most of the time is just with
| | 03:06 | that little piece of code.
| | 03:07 | Now the way that this works, you'll
notice our constructor here in our Animal
| | 03:11 | class, down beginning on line 35, it
simply checks the arguments that were
| | 03:18 | passed, and if any of them are of
length zero, it throws an exception with a
| | 03:22 | message that says insufficient parameters.
And so when we run this, because we
| | 03:28 | actually called this way on purpose--
if you look down here, we're calling it
| | 03:31 | with an empty parameter there for the
sound--and so when we compile this and run
| | 03:37 | it, you see that we get a message that
says Animal x: Insufficient parameters,
| | 03:42 | and if we look up here at
our constructor, there is our
| | 03:44 | exception that gets thrown, a little
temporary E object that's constructed with
| | 03:49 | insufficient parameters as its string.
| | 03:52 | And so that'll set it up to have what
return that string, and when we come
| | 03:58 | down here in our catch clause, we see
that we call what on that object, and we
| | 04:02 | get that string there.
| | 04:03 | So this is really a very simple
way to take advantage of exceptions.
| | 04:07 | Exceptions in C++ have a lot of
different ways that you can use and a lot of
| | 04:12 | things you can do with it, but 9 times out of 10,
you just need it to give you an error message.
| | 04:18 | And so this is a great way to do that.
| | 04:20 | So this is just a quick introduction
to exceptions in C++, but it's a useful
| | 04:24 | example and the E class can
easily be adapted for your usage.
| | 04:27 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
|
|
9. InheritanceOverview of class inheritance| 00:00 | Class Inheritance is the ability to reuse
code by deriving a class from a base class.
| | 00:06 | The derived class will typically
inherit and build upon some or all of the data
| | 00:11 | and function members of the base class.
| | 00:14 | Let's take a look at some of the
terminology involved in class inheritance.
| | 00:18 | The base class is a class that has
members that are to be used in the new class,
| | 00:23 | sometimes called the
superclass or a parent class.
| | 00:27 | The derived class is the class that is
being created and is based upon the base class.
| | 00:32 | Sometimes this is called a
sub class or a child class.
| | 00:38 | There are three different levels of
member access, these access levels determine
| | 00:43 | what other objects would be
able to access class members.
| | 00:46 | They are specified by the
Member Access Specifiers.
| | 00:50 | Members given public access
are available to all objects,
| | 00:54 | those are the base class, the
derived class, and other unrelated objects.
| | 00:59 | Protected access members are available to
members of the base class and the derived class.
| | 01:05 | And private access members are
only available to the base class.
| | 01:09 | In addition to adding members to a
class, derived classes may also overload
| | 01:14 | members of its base class.
| | 01:16 | Overloaded members are used for changing or
customizing certain behaviors of the derived class.
| | 01:22 | Class Inheritance is a way to reuse
code by basing one class on another class
| | 01:28 | and customizing behaviors to match usage.
| | 01:30 | C++ provides complete support for class
inheritance, including overloading methods,
| | 01:35 | polymorphism, and multiple inheritance.
| | Collapse this transcript |
| Exploring simple inheritance| 00:00 | Class inheritance in C++ is simply a
matter of creating a base class and then
| | 00:05 | declaring the inheritance
in your class definitions.
| | 00:08 | Let's take a look at the simple example.
| | 00:10 | So let's make a working copy of simple
inheritance.cpp from our exercise files
| | 00:15 | Chapter 9, and we'll paste this into the
Working project and double-click on it to open it up.
| | 00:21 | I am going to go ahead and maximize this.
| | 00:23 | In this case we have a base class called
Animal and three classes that inherit from it.
| | 00:28 | We have Dog, Cat, and Pig.
| | 00:31 | So Animal is the base class, and Dog
Cat and Pig are the derived classes.
| | 00:37 | Some people use the terms parent
and child, but that's not as common.
| | 00:40 | The Animal class is really very simple.
| | 00:43 | It has three private data members for
the name, type, and sound of the animal.
| | 00:48 | It has a public method called
speak and a protected constructor.
| | 00:52 | The protected access specifier may be new to you.
| | 00:55 | It means that these members are only
accessible through derived classes.
| | 01:00 | So by having the constructor of
protected access and the default constructor as
| | 01:06 | private access, really making sure that
this base class cannot be instantiated
| | 01:11 | on its own, only its derived
classes may be used as objects.
| | 01:16 | So if you have a class that you don't
want to have used by itself, this is a
| | 01:19 | good way to prevent it from being constructed.
Now let's take a look at the Dog class.
| | 01:27 | Notice on line 28, we declare the class Dog,
and we declared as inheriting from Animal.
| | 01:32 | So there's a colon followed by an
access specifier and the name of the class
| | 01:37 | that is being inherited,
the name the base class.
| | 01:40 | The access specifier here is a little bit
different than what we might be used to.
| | 01:45 | This basically controls how the base
class members will be accessed by code that
| | 01:50 | uses your derived class.
This will almost always be public.
| | 01:55 | It's very, very rare to see
any other access used here.
| | 01:58 | Now notice the constructor for the Dog
class on line 31, it has initializers
| | 02:05 | that call a base class constructor and
initialize a private member variable.
| | 02:10 | So you see right here we're actually
calling the constructor for the base class,
| | 02:18 | and we're providing it with the name
and the sound for the Dog, and here we're
| | 02:24 | initializing our own private data
member which is not part of the base class.
| | 02:28 | And you'll notice I've also provided
a public method for walking the Dog.
| | 02:33 | So the Cat Class is very similar.
| | 02:36 | It inherits also from Animal, it has
its own private data member for how many
| | 02:40 | times it's been petted, and the Pig
class again works the same way and has its
| | 02:44 | own private data member for its being fed.
| | 02:48 | So here in main, we instantiate three
objects,l 1 Dog, 1 Cat, and 1 Pig, we give
| | 02:54 | them names, and we go ahead and use them.
| | 02:56 | So let's bring this back down, and we'll
compile and run it and look at the results here.
| | 03:06 | So here we're calling speak for each
of these, and the speak method is in our
| | 03:11 | base class and its right here.
| | 03:14 | It says name the Animal says sound so
here we have Rover the Dogs says Woof,
| | 03:21 | Fluffy the Cat says Meow, Arnold the Pig
says Oink, and we've seen where these
| | 03:26 | names come from. The type of Animal and the sound
is in these constructors in the derived classes.
| | 03:34 | And the name of the Animal--in this
case Rover, Fluffy, and Arnold--that gets
| | 03:38 | passed into that constructor for each
Animal, and then it gets passed to the base
| | 03:43 | class in that constructor.
| | 03:46 | And now here I walk the dog, I pet
the cat, and I feed the pig, and you see
| | 03:52 | that, that increments these counts.
| | 03:54 | So for instance, if I walk
the dog a few more times.
| | 03:57 | Let's come down here to the end,
and we'll compile that and run it.
| | 04:03 | We see the dog has been walked
two times and then three times.
| | 04:07 | So class inheritance in C++ is really very simple.
It's also very powerful.
| | 04:12 | We will look at some more complex
examples in the rest of this chapter.
| | 04:15 | Now let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Reviewing friendship| 00:00 | Sometimes you want to grant access to
a class's private variables to another
| | 00:04 | object or even a few select objects.
| | 00:07 | This is accomplished with a friend declaration.
Let's take a look at an example here.
| | 00:12 | We'll make a working copy of simple inheritance.cpp
and paste it into our Working project.
| | 00:16 | I'm just going to maximize this and
page through it real slowly for those who
| | 00:21 | are typing along at home.
| | 00:28 | Now, if we go ahead and compile and
run this, we see that it's working just fine.
| | 00:34 | And of course, this was described
in our last movie on simple inheritance,
| | 00:40 | it basically has these three classes that are
derived from a base class, Dog, Cat, and Pig.
| | 00:45 | Now each of these classes actually
calls a constructor in the base class.
| | 00:50 | So here we see Dog calls the constructor
in Animal and Cat calls the Constructor
| | 00:56 | in Animal and Pig also calls the
constructor in Animal and the constructor at
| | 01:01 | Animal is in the protected section.
| | 01:03 | Now, if I move this constructor to the
private section, I can just get rid of
| | 01:09 | that, because that's the only thing
in the protected section, and now I've
| | 01:14 | changed the access from protected
to private for that constructor.
| | 01:19 | So if I save this, and I try to compile
and run it, you'll see that it doesn't work.
| | 01:25 | So one way to grant access is by
putting it in that protected section, giving
| | 01:30 | it protected access. Another way to do
this is to add our derived classes as friends.
| | 01:35 | So we can do this right here, and we can say
friend class Dog; friend class Cat; and friend class Pig;
| | 01:51 | This technique exposes all of the private
members of the base class to the derived classes.
| | 01:56 | So if I now compile and run this,
you'll see that our example is working just
| | 02:03 | fine, and we're able to
access those constructors.
| | 02:08 | So now those derived classes have access
even to the private members of the animal class.
| | 02:13 | This also works for functions.
| | 02:16 | So, if I come down here and create a
function, this function is trying to access
| | 02:33 | a private data member from the Animal class.
| | 02:36 | Now I come down here, and I say
cout << "The dog is named " << get_animal_name(d), D for dog.
| | 02:52 | Now of course, this isn't going to work,
because my function is trying to access
| | 02:55 | a private data member.
| | 02:56 | So, I'll try and run that,
and we get compiler errors.
| | 02:59 | Now we see here within this context
that it's trying to access this private
| | 03:06 | data member right here.
| | 03:09 | So, if I declare that function as a
friend like this, and I can just take its
| | 03:17 | function signature from down here and
copy and paste it, and I'll actually need
| | 03:28 | the name of the variable
there and put in a semicolon.
| | 03:31 | Now when I try to compile and run this,
it works just fine, and it says
| | 03:37 | The dog is named Rover, and now the function
has access to the private data member.
| | 03:42 | Of course, this function now has access
to all of the private data members, and
| | 03:48 | this can of course be convenient, but
it can also undermine encapsulation and a
| | 03:52 | lot of controls that make object-
oriented programming, work so well.
| | 03:56 | It's usually safer to use an accessor.
And so we--of course--we do that like
| | 04:00 | this, and then I can remove this from the friend
and compile and run it, and it works just fine.
| | 04:11 | So the friend declaration allows you
to grant private member access to other
| | 04:15 | classes and functions, and this can
be handy at times, and it may even be
| | 04:20 | necessary at times, but it
needs to be used with caution.
| | 04:23 | Most of the times it's best practice to access
private members through the class interface.
| | 04:28 | So let's go ahead and delete our Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Accessing the base class| 00:00 | When you're creating classes with
inherited base classes, it's sometimes
| | 00:04 | necessary to access member data
and functions from the base class.
| | 00:08 | Let's take a look at how to do this.
| | 00:10 | Make a working copy of simple-inheritance.cpp,
and I am going to paste that in our Working project.
| | 00:16 | Let me just maximize this and scroll
through it real briefly for those of you
| | 00:20 | are typing along at home.
| | 00:26 | So this is our simple inheritance
example, and it has this base Animal class
| | 00:30 | that gets inherited by these derived
classes, Dog, Cat, and Pig, and we initialize
| | 00:37 | a Dog, a Cat, and a Pig down here,
and we print out some data from them.
| | 00:41 | And that looks like that,
when we compile and run it.
| | 00:43 | Now let's say, for example, that we
wanted to add a method to the pig to speak
| | 00:48 | its name Pig Latin, so we came down here,
and we can say like that, and then we
| | 00:59 | can write the method itself.
| | 01:04 | And that will take the name of the
animal, and it will append -ay to the end of
| | 01:10 | it which we all know anything into pig Latin.
| | 01:13 | Of course there are lots of other
fun rules for constructing Pig Latin.
| | 01:16 | For our purposes, it will do to just
add -ay at the end of the word, and we
| | 01:20 | can call it like this.
| | 01:26 | And so I will just compile and run it you
will see that it works, and it says Arnold-ay.
| | 01:31 | So in this Pig Latin method, you will
notice that I accessed the name method
| | 01:35 | from the base class, which is Animal.
| | 01:38 | In order do this, I use the name of
base class, Animal, followed by two colons
| | 01:43 | and followed by the name of
the method that I am accessing.
| | 01:47 | This specifies that the
method is in the base class.
| | 01:50 | So this syntax isn't strictly
necessary here because there's no conflicting
| | 01:55 | name in the derived class, but it's worth
noting, and it's actually worth doing it this way
| | 02:00 | because it can be necessary under
other circumstances, and we will see some
| | 02:04 | examples of that later in this chapter.
| | 02:05 | Now let's delete our Working file and
run Clean to get set up for next lesson.
| | Collapse this transcript |
| Understanding multiple inheritance| 00:00 | Multiple-inheritance is the
technique of inheriting from multiple base
| | 00:05 | classes, and in C++ it's simply a matter of
listing the base classes in the class definition.
| | 00:10 | Let's take a look at a quick example.
Make a working copy of simple-inheritance.cpp.
| | 00:15 | I'm going to paste that into a
Working project and open here--just take a
| | 00:19 | moment and maximize this and scroll through it
real quickly for those who are typing along at home.
| | 00:27 | So this is a very simple example of a
base classl and some derived classes.
| | 00:31 | The Base class is Animal and the
derived classes are call Dog, Cat, and Pig.
| | 00:36 | And if we bring this back down to size,
and we will compile and run it--press
| | 00:42 | the big green compile and run button
there--and we'll see that, that's how it
| | 00:46 | works down here in our main function.
| | 00:49 | We instantiate three objects from our
derived classes, a Dog, a Cat, and a Pig, and
| | 00:54 | they speak, and we also walk the
dog and pet the cat and feed the pig.
| | 00:58 | Now let's create another base class here,
and we'll go ahead and we will enter
| | 01:04 | this right after the Animal class, and
we'll call this fur class, and this will
| | 01:07 | be for the type of fur, and
we need a string for that type.
| | 01:14 | And we'll create a private default constructor
so that it cannot be constructed on its own.
| | 01:19 | And a protected constructor for
use by the drive class, and you can call
| | 01:29 | that with the type of fur in a string.
| | 01:32 | And then we'll also create a public
method to access the type string, and we
| | 01:42 | actually don't need this namespace
qualifier here because we were importing that
| | 01:47 | entire name space up at the top.
| | 01:50 | Using namespace standard there on
line 3, that means we don't need to that.
| | 01:54 | So there's our fur class,
very simple and straightforward.
| | 01:57 | Now let's go down to the Cat, and we'll
have the Cat inherit the fur class as well.
| | 02:03 | So put in a comma, and public and fur.
| | 02:07 | Now the Cat is actually deriving
from two base classes, Animal and Fur.
| | 02:12 | And then in the constructor for Cat--
I am going to go ahead and maximize
| | 02:17 | here so we can see this.
| | 02:18 | In out list of initializers, I am going
to add Fur, and we'll say that the Cat's Fur
| | 02:26 | is silky, and now let's
add a grooming method to Cat.
| | 02:31 | Come down here, and we'll define the
method, and you will notice that we are
| | 02:40 | specifying the two different base classes here.
| | 02:42 | Animal name, which actually
does not have a name conflict.
| | 02:46 | So if I were to just say name,
that would work in this case.
| | 02:49 | But Fur type does have a name conflict.
| | 02:51 | If I were to omit the Fur::,
the compiler would not know what to do
| | 02:56 | with that because there is a type
method in both of the base classes.
| | 03:01 | I come up here to class Fur, you see
there's type on line 33, and you come up
| | 03:07 | here to the class Animal,
and there is a type on line 19.
| | 03:12 | So we'll come down here, and we will
put in and cout for c.grooming--
| | 03:22 | actually we have the whole cout there
in the method, don't we? We can just
| | 03:26 | put it like this, and we'll bring us
back down to size, and we will save it and
| | 03:31 | compile and run it. And there it
says Fluffy grooms her silky fur.
| | 03:36 | Multiple-inheritance in C++ is
really very simple, perhaps too simple.
| | 03:40 | While sometimes it really is necessary,
many times it can create unnecessary complexity.
| | 03:45 | For example, this example may have been
more clear if the Cat class used a fur
| | 03:51 | object as a property rather than inheriting it.
| | 03:54 | The code would be simpler and easier
follow, and the type method would no
| | 03:57 | longer be ambiguous.
| | 03:59 | So let's go ahead and delete our Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
| Exploring overloading methods and polymorphism| 00:00 | Sometimes it's useful to overload a
method that's defined in a base class.
| | 00:04 | Let's take a look at how this is done.
| | 00:06 | We'll make a working copy of simple-inheritance.cpp
from our Chap09 folder of the ExerciseFiles,
| | 00:12 | and we'll paste that into our Working
project and open it up here.
| | 00:16 | I am going to maximize this and just
scroll through it really slowly so that
| | 00:21 | those who are typing along
at home may follow along.
| | 00:27 | And this is the same example we've
been using throughout this chapter.
| | 00:30 | It's got a base class called Animal that gets
inherited by three derived classes, Dog, Cat, and Pig.
| | 00:39 | And then these are instantiated to
objects in main, and we call speak method on
| | 00:47 | the base class and the walk, pet,
and feed methods on the derived class.
| | 00:52 | So we'll go ahead and just compile and
run this, and you can see how it works.
| | 00:57 | And so down here in main, you see we
call speak three times for each of them,
| | 01:02 | Rover the dog says woof, Fluffy the cat
says meow, Arnold the pig says oink, and
| | 01:08 | then we walk the dog, pet
the cat, and feed the pig.
| | 01:11 | Let's say that we just want to change
the speak method just for the cat.
| | 01:16 | We can do that by overwriting the speak method
in the cat class, and that works like this.
| | 01:27 | First, we create a speak
function member in the cat.
| | 01:31 | And you notice that Eclipse gave us
this little purple triangle, and if I hover
| | 01:36 | over that it says Shadows Animal::speak,
and that's because up here in Animal,
| | 01:43 | there is a member
function called speak on line 17.
| | 01:49 | So now let's go ahead and define it.
We have declared it, now we'll define it.
| | 01:57 | And there we have that same little purple
triangle there, Shadows Animal::speak, and
| | 02:02 | we'll just simply say cout << "purrrrr" << endl;
| | 02:10 | So now when we compile and run this, we
really don't have to do anything else.
| | 02:14 | When we compile and run this, you'll
see that the cat is purring instead of
| | 02:18 | saying Fluffy the cat says meow.
| | 02:21 | And that's because this version of
speak is being called instead of the
| | 02:24 | Animal version of speak.
That was pretty easy.
| | 02:28 | In fact, if we want to also call the
base class method, we can simply say
| | 02:33 | Animal::speak right there inside of Cat::speak,
and we can compile and run that,
| | 02:40 | and then we'll get both.
| | 02:42 | You'll notice here, Fluffy the cat
says meow and purrrrr. All right.
| | 02:46 | For right now I am just going to have
the purrrrr in there, compile and run one
| | 02:51 | more time so we can see that we
have that, we have just the purrrrr.
| | 02:55 | And so that's doing exactly what we
expected to do, pretty easy, right?
| | 02:58 | There is however one problem with this
still, and in order to see that problem
| | 03:03 | let's create a generic pointer and see
if we can access all of these methods
| | 03:07 | from the generic pointer.
| | 03:08 | So I am going to go I am
going to delete all of these calls to
| | 03:11 | speak that are off of the objects, and I am
going to create an array of Animal pointers.
| | 03:19 | And I am going to initialize that array
to the addresses of these three classes.
| | 03:28 | And I am going to terminate it
with a null pointer.
| | 03:30 | I am using the C++11 null
pointer keyword here.
| | 03:35 | You'll notice that my version of
Eclipse is complaining about that, and it says
| | 03:40 | Symbol nullptr could not be resolved,
but in actuality when I compile and run
| | 03:45 | this because I'm using a version of GCC
that understands C++11, it will actually
| | 03:50 | compile and run just fine.
| | 03:51 | That's just a problem with this
version of Eclipse, and if you have a later
| | 03:55 | version of Eclipse, it may
actually not be doing that anymore.
| | 03:57 | So now I am going to create a little for
loop to loop through these pointers and
| | 04:02 | call the speak method on them.
| | 04:07 | And that's as simple as that, and so
now rather than calling d.speak, c.speak,
| | 04:13 | and p.speak, we're actually
generalizing this because its code that gets run
| | 04:18 | more than once, this is a
very common thing to do.
| | 04:22 | And so we have a generic
pointer, it's an Animal pointer.
| | 04:25 | It's a pointer to the base class, which
actually should work just fine for each
| | 04:30 | of these derived classes.
| | 04:32 | And we have that array of those pointers,
and we're iterating through that array
| | 04:35 | and calling speak on each one of those pointers.
So let's go ahead and compile and run this.
| | 04:42 | So you can see this appears to be
working just fine except that oh, you'll
| | 04:46 | notice it says fluffy the cat says
meow, it's not calling the derived class
| | 04:51 | speak, it's calling the base class speak.
| | 04:54 | So, we're already using an Animal
pointer here, so it appears to just be
| | 04:58 | calling the Animal method for all of these,
and it's ignoring the derived method for Cat.
| | 05:05 | So there is a way to fix this and the way to
fix this is to declare speak as a virtual method.
| | 05:13 | And so I am going to use the virtual
keyword here, and that's a qualifier, and
| | 05:19 | that qualifies that speak
method as being inheritable.
| | 05:23 | And you'll notice when I add that
virtual keyword, that virtual qualifier, you
| | 05:28 | notice we get a little warning on each
of our derived classes here, and it says
| | 05:32 | has virtual method speak
but non-virtual destructor.
| | 05:36 | So what this means is that whenever
you declare a virtual method in a base
| | 05:42 | class, you need to also declare a
virtual destructor, and that looks like this.
| | 05:48 | And that simply lets the destructor
in each of the derived classes also
| | 05:53 | overload the destructor in the base class.
And this is really important because
| | 05:57 | this makes sure that the destructor
that's actually called matches the object
| | 06:03 | that's being destroyed.
| | 06:05 | In other words, if we're allowing
certain methods to be overloaded in derived
| | 06:10 | classes through a generic pointer,
through a pointer to the base class, when
| | 06:15 | that object is destroyed, if it's also
destroyed through a pointer to the base
| | 06:20 | class, this will make sure that the
appropriate destructor is actually called.
| | 06:27 | Even though Eclipse put up a warning
there, it's not actually a hard class
| | 06:30 | requirement, but 99 times out of 100
it's the right thing to do.
| | 06:35 | So now we have our virtual speak and
our virtual Animal, and so if I simply
| | 06:40 | compile this and run it--I am going to
save first and compile and run--now we
| | 06:45 | see that even though we're using this
generic pointer, and this pointer has been
| | 06:49 | declared as type Animal, when we call
it on a cat object, it calls the derived
| | 06:56 | version of the overloaded class.
| | 06:59 | You'll also notice that up here in
this little green arrow, it now says
| | 07:04 | Overrides Animal::speak.
| | 07:06 | If we didn't have the virtual in here--
and I am just going to go I am
| | 07:11 | going to remove the virtual there and save that.
| | 07:13 | And we'll come down here, and we'll
see that the little arrow has a different
| | 07:17 | color, and it says Shadows Animal::speak.
| | 07:19 | So that's just something that Eclipse is
doing for us to show us the distinction.
| | 07:23 | Shadow means that it's not virtual and
Overrides means that it is virtual, so
| | 07:29 | the now the little arrows are
green and they say Overrides.
| | 07:32 | So overloading methods in derived
classes is a fundamental part of
| | 07:35 | polymorphism, and this gives you a lot of power
and flexibility in how you design your classes.
| | 07:40 | By using the virtual qualifier, your overloaded
methods can even be called through generic pointers.
| | 07:47 | Now let's go ahead and delete our Working file
and run Clean to get set up for the next lesson.
| | Collapse this transcript |
|
|
10. TemplatesUnderstanding templates| 00:00 | C++ templates are
marvelously simple and powerful.
| | 00:04 | In C++ templates are the feature
that supports generic programming.
| | 00:08 | In general terms generic programming
refers to programming in terms of
| | 00:12 | algorithms independent of types.
| | 00:15 | Generic programming refers to
code works independent of type.
| | 00:18 | While C++ is a strongly typed language,
there's still great benefit in being able
| | 00:23 | to write functions and classes that are
type agnostic, that is they operate on
| | 00:28 | objects without concern for
the type of those objects.
| | 00:31 | Because C++ supports defining your
own types through classes of operator
| | 00:36 | overloading, it's possible to do a
great deal of generic programming and
| | 00:40 | templates while leaving implementation
details to class as an operators.
| | 00:45 | Template declarations look just like normal function
or class declarations with one distinction.
| | 00:51 | They are preceded by the template
keyword and a set of type identifiers.
| | 00:56 | These type identifiers are used as place
folders by the template code to be replaced
| | 01:01 | during compilation with actual types.
| | 01:04 | When a function or class is
instantiated from a template, the compiler generates
| | 01:08 | a specialization of that function or
class specifically suited to the types
| | 01:13 | specified in instantiation.
| | 01:15 | Templates are widely used in the C++
standard library which is why parts of the
| | 01:20 | library are commonly called
the standard template library.
| | 01:23 | The generic nature of template classes makes
them a perfect fit for use with containers.
| | 01:28 | Templates programming is not
entirely without its downsides.
| | 01:32 | There some issues you need to be aware
of. Overuse of templates can lead to code
| | 01:37 | bloat and longer build times.
| | 01:39 | Because the compiler must generate specializations
for every instantiation of the template.
| | 01:43 | The amount of code to support
that template can grow rapidly with use.
| | 01:48 | Compilers tend to have a difficult time
generating sensible error messages with
| | 01:52 | templates, so debugging can be challenging.
| | 01:55 | And because templates tend to live in
header files, changes to header files with
| | 01:59 | templates can lead to recompilation of
a larger portion of your code than would
| | 02:03 | otherwise be necessary.
| | 02:05 | C++ templates are a very powerful feature
that is also simple to implement and support.
| | 02:12 | They have great advantages over
other generic programming solutions--in
| | 02:15 | particular preprocessor macros--and they
are widely used to implement containers
| | 02:20 | and other generic objects
in the C++ standard library.
| | Collapse this transcript |
| Understanding template functions| 00:01 | C++ supports both template functions
and template classes.
| | 00:04 | In this movie, we will
looking at template functions.
| | 00:07 | Let's make a working copy of
template-function.cpp, and we'll paste it into our
| | 00:12 | Working project here.
| | 00:14 | Here we have a simple example of a
template function that gives the maximum
| | 00:17 | value of two parameters. The keyword
typename is commonly used here on line 5
| | 00:24 | to indicate the type that will be templated, but
the keyword class also works and is often used.
| | 00:30 | Just be aware that at least in this
context, either of these tokens means
| | 00:33 | exactly the same thing.
| | 00:36 | The simple template is both
type agnostic and type safe.
| | 00:40 | It's type agnostic in that it'll
work for any type that has support for the
| | 00:45 | greater than operator, and it's type safe
in that the compiler will generate a
| | 00:49 | specialization of the
function for that given type.
| | 00:53 | So if we call it as we have in line
10 with two integers, it'll generate a
| | 00:58 | specialization of the function that
operates on type int and returns type int.
| | 01:04 | So I am just going run compile and run here,
and you'll see that our result is int.
| | 01:09 | And if I change this so that it has
two string literals, now it'll
| | 01:16 | generate a specialization that works
on cStrings and returns a cString, so
| | 01:22 | compile and run, and we see that it
thinks, the aaaaa is larger than the
| | 01:27 | baaaa, and that's because cstrings
don't actually work very intelligently with
| | 01:32 | greater than operator.
| | 01:33 | On the other hand, if we tell this to
use the C++ string class instead--now we
| | 01:40 | can do that by specifying it like that--
and now we compile and run it, we see we
| | 01:47 | get a more intelligent result because
the C++ string class actually supports the
| | 01:51 | greater than operator properly.
| | 01:53 | So let's take a look at a
slightly more complex example.
| | 01:57 | Go ahead and delete this, and we'll run
Clean, make a working copy of join.cpp
| | 02:06 | there out of our Chapter 10 folder in
the exercise files, and open it up, let's
| | 02:11 | maximize this so that we can see it,
and I'm just going to scroll a little bit
| | 02:16 | so that those folks who are
typing along at home can follow us.
| | 02:20 | So this function will take any container,
and it'll join the elements into a new
| | 02:26 | container with a separator between
each element and return the new container
| | 02:31 | And down here in main, we'll see a
couple examples of how this is used.
| | 02:35 | The first example on line 23 joins the
characters of the string with a separator
| | 02:41 | of a colon into a new string, And the
version done on line 27 joins
| | 02:47 | strings from the vector, and it
separates them with comma and a space.
| | 02:52 | So let's take a look at how this works.
| | 02:54 | So you see that the template
declaration specifies three different types:
| | 03:00 | the containerType, the returnType,
and the separatorType, so these
| | 03:03 | can all be the same or
they can be three different types.
| | 03:07 | You'll notice the two of them have
default types, the second one here,
| | 03:13 | typenmae retT = cT,
and so if a returnType is
| | 03:19 | not specified it will default to
containerType, and the third one is little
| | 03:23 | bit more complex, separatorType,
and if it's not specified, then it'll
| | 03:28 | default to the value_type
of the containerType.
| | 03:33 | So you can see you can do a lot with
this most of the time this level of detail
| | 03:37 | is not necessary but I just wanted
to show you how powerful this can be.
| | 03:41 | The function itself it returns the
returnType, and it takes two arguments
| | 03:47 | an object of the containerType and
an object of the separatorType.
| | 03:51 | It declares a temporary variable
for the returnType called out.
| | 03:56 | It sets up an iterator, and it
iterates through the container and takes each
| | 04:01 | object and concatenates it into the out
container, and if we're not at the end
| | 04:07 | it adds a separator to out, and then
it returns out, it's really very simple.
| | 04:14 | So let's go ahead and bring this back
down and run it. So we'll press the compile
| | 04:19 | and run button there, and
we see how powerful this is.
| | 04:23 | We taken a string, s1, that says this is a
string, and it's taken each character and
| | 04:29 | separated them out by colons and
created a new string with that result.
| | 04:34 | And then it takes a vector of strings,
which is like an array of strings--so
| | 04:39 | factor is a C++ containerType,
and so it's got all three of those
| | 04:43 | strings, this is a string,
this is also strange, yet another string--
| | 04:47 | and it joins them into a string--see
it's output container is specified as
| | 04:53 | string, and a separator is a string
containing a comma and a space--and so our
| | 04:58 | result here is all these strings separated by
a comma and a space all in one string.
| | 05:04 | So you can see how powerful and flexible this is,
and it's just this simple bit of code here,
| | 05:08 | and it can do all of that, and it can
work in all these different types.
| | 05:12 | It can really work with any
containerType that supports those operators.
| | 05:16 | It just needs to support that plus equal
operator, and that's really all that's necessary.
| | 05:24 | So template-functions are a form
generic programming that are easy to create
| | 05:29 | and can be very powerful and very
useful. For many of the purposes that we used
| | 05:33 | to use C macros, C++ template functions are more
powerful, more flexible, and less prone to error.
| | 05:40 | Let's delete our Working file and run
Clean to get set up for the next lesson.
| | Collapse this transcript |
| Using template classes| 00:00 | Template classes are commonly
used for operating on containers.
| | 00:04 | Let's take a look at template-class.cpp and make
a copy of it and paste it into our Working project.
| | 00:12 | Open it up in the editor, and I'm going
to maximize it here so that we can see it.
| | 00:16 | So this class, you'll notice at the top
here I've an exception class, and that's
| | 00:21 | explained actually in the chapter on C++
classes, and I'll show you how that's
| | 00:26 | used, but this is the same class
that's used there, and it's one that you're
| | 00:30 | welcome t |
|
|