This is a very high-level overview of C++. It does not seriously address the hard stuff, like inheritance or generics.
For a short high-level view of C++, check out Eric Brasseur’s C++ tutorial for C users. If you want more, check out C++ Primer Plus (6th edition). It was just published last month and is the successor to this semester’s C Primer Plus (5th edition)
Some of the new feature of C are straightforward and useful extension.
You can start comments with //
and don't have to put all
your declarations at the front of a block.
{ double i ; // C++ is happy to ignore this comment! i = sqrt(2.0) ; // You can declare after an assignment! int sum = 0 ; // You don't even to declare loop variables before they are used for (int n=0; n<100; ++n) { sum = sum + n ; }
C++ has extraction and insertion operators
that simplify I/O. Students in an introductory
C++ course will never use printf
or scanf
or %d
or %f
.
#include <iostream> using namespace std ; int principal ; double interest ; cout << "Enter the principal (in whole dollars)." << endl ; cin >> principal ; cout << "Enter the interest rate." << endl ; cin >> interest ;
However, setting field width is weird, and sometmes you
know printf
would have been easier.
#include <iostream> #include <iomanip> using namespace std ; for (int sq=0; sq<100; ++sq) { cout << setw(3) << sq << " squared " << " is " << setw(6) << sq*sq << endl ; }
C++ has references that can be used in place of pointers used to “pass” multiple variables to a procedure. Here’s a “function” to sort two variables in C.
void swap(int *x, int *y) { if (*x > *y) { int t ; t = *x ; *x = *y ; *y = t ; } } int a, b ; swap(&a, &b) ;
In C++ you can do this with far fewer special operations.
void swap(int &x, int &y) { if (x > y) { int t ; t = x ; x = y ; y = t ; } } int a, b ; swap(a, b) ;
The real C++ is a serious object-oriented programming language. You’ve seen structures with data, which we called fields. Now you are going to see classes with procedures, which we will call methods.
Let’s start by thinking about a “box” similar to the one encountered in the Fall 2011 Project P8. There a box was represented by upper-left and lower-right points. We can put this information in a C structure in a rather straightforward way.
struct box { int UpperLeftX ; int UpperLeftY ; int LowerRightX ; int LowerRightY ; } ;
Creating one of these structures and initializing it is more tedious than fun.
Here’s a dynamically allocated one.
struct box *P = (struct box *)malloc(sizeof(struct box)) ; P->UpperLeftX = 4 ; P->UpperLeftY = 5 ; P->UpperRightX = 12 ; P->UpperRightY = 12 ;
The statically allocated one really isn’t much better.
struct box Q ; Q.UpperLeftX = 4 ; Q.UpperLeftY = 5 ; Q.UpperRightX = 12 ; Q.UpperRightY = 12 ;
That initialization and declaration can be shortened, with a some reduction of readability as follows.
struct box Q = { 4, 5, 12, 12 } ;
If all you want is fields,
the C++ class
can be to mimic the C struct
;
but you must define your fields in the public
section
of the class.
class box { public: int UpperLeftX ; int UpperLeftY ; int LowerRightX ; int LowerRightY ; } ;
Variables may be declared using a class
, but you
don’t include “class
” in the
declaration.
box *P ; box Q ;
It’s also a little easier to allocate and free dynamic
variables in C++ using the new
and delete
operators.
P = new box() ; delete P ;
The new
operator alone might be enough to entice
some C programmers to trade in their
struct
’s for class
’s.
However, the true C++ programmer rarely uses fields. Instead, they use
methods, or member functions, to access and modify their data structures.
Here is a C++ class
definition for the box.
The const
qualifier is used for
methods that do not modify objects of the class.
class box { public: int GetUpperLeftX() const ; int GetUpperLeftY() const ; int GetLowerRightX() const ; int GetLowerRightY() const ; void SetUpperLeftX(int) ; void SetUpperLeftY(int) ; void SetLowerRightX(int) ; void SetLowerRightY(int) ; private: int UpperLeftX ; int UpperLeftY ; int LowerRightX ; int LowerRightY ; } ;
Notice that all the fields are private. Accessor
methods, such as GetUpperLeftX
, and mutator
methods, such as SetUpperLeftX
, replace field
references.
P->SetUpperLeftY(5) ; x = Q.GetUpperLeftX() ;
Usually a class is defined in an interface (or header) file. An implementation file contains the C++ statements needed to satisfy the specification.
The C++ syntax for defining methods is a bit unexpected.
int box::GetUpperLeftX() const { return UpperLeftX ; } void box::SetUpperLeftX(int newULX) { UpperLeftX = newULX ; }
In C++ ::
is scope resolution operator that
associates a member function with a specific class. It allows
variable names, such as UpperLeftX
, to refer to
fields of the class object.
Almost all C++ method calls can be implemented by simple function calls.
This is done by
mangling
the name of the method.
For example box::SetUpperLeftX
might be
mangled to _ZN3box13SetUpperLeftXEi
. (That’s a real
example.)
Then a call like P->SetUpperLeft(x)
can be transformed to _ZN3box13SetUpperLeftXEi(P, x)
;
or Q.SetUpperLeft(x)
, to
_ZN3box13SetUpperLeftXEi(&Q, x)
Still, you do have to wonder about the cost of a function call versus
executing a simple assignment statement, such as
Q.UpperLeftX = x
.
Don t worry, the price can be significantly reduced by the
use of inline function defintions within the
interface file.
For example, if an alternative
interface file for box
use inline member function definitions, similar to those seen below,
the function call would be replaced with an single assignment statement.
void SetUpperLeftX (int newULX) { UpperLeftX = newULX ; }
In this case, you may not even need an implementation file.
In C++ it is possible to describe specialized constructors that create and initialize objects.
box(int, int, int, int) ;
box::box(int initULX, int initULY, int initLRX, int initLRY) { SetUpperLeftX (initULX) ; SetUpperLeftY (initULY) ; SetLowerRightX(initLRX) ; SetLowerRightY(initLRY) ; }
box *P = new box(4, 5, 12, 12) ; box Q(4, 5, 12, 12) ;
It is possible to have several member functions with the same name, as long as they accept different numbers or types of arguments.
// Sets both corners of the box void SetCorners(int, int, int, int) ; // Sets both corners of the box to the same point void SetCorners(int, int) ;
Is is possible to redefine the operators of C++. For example,
in a Point
class it would be possible to
add a +
operator that performs vector addition.
Frequently the insertion operator is overloaded.
Here's an example for the box
class.
std::ostream& operator<<(std::ostream &sout, const box &b) { sout << "(" << b.GetUpperLeftX() << "," << b.GetUpperLeftY() << ") -> (" << b.GetLowerRightX() << "," << b.GetLowerRightY() << ")" ; return sout ; }
Now you can write a box
with a single statement.
cout << *P ;
Classes can be extended. The extended class is a subclass of the original. For example, there are boxes and there are boxes with character.
class LetterBox: public box { public: char GetCharacter() const { return letter ; } void SetCharacter(char letter) { this->letter = letter ; } private: char letter ; }
Methods belong to the superclass may be invoked even though they are not explicitly defined for a class.
LetterBox A ; A.SetCharacter('A') ; A.SetUpperLeftX(13) ;
C++ has a Standard Template Library (STL) that implements almost all the standard data structures. In C++, you don’t program linked lists. You use them!
list<box> packages ;
Many C++ classes have been written for use on the Arduino. A little knowledge of C++ would be very useful for using these libraries.