| include directives | #include <iostream> |
| comments | // what this does |
| constant definitions | const double pi = 3.14159; |
| global variables | int count; |
| function definitions | int foo(int x) { ... } |
| class definitions | class Foo { ... }; |
class Date {
As in Java, C++ classes contain:
int day, month, year;
Date() ...
Date(int d, int m, int y) ...
int get_day() { return day; }
...
};
class Date {
private:
int day, month, year;
public:
Date() ...
Date(int d, int m, int y) ...
int get_day() { return day; }
...
};
In this case, the fields are private,
and the constructors and methods are public.
const int days_per_week = 7;
int last(const vector<int> &v) { ... }
We can indicate that the function get_day() doesn't change the
state of the object by changing its declaration to
int get_day() const { return day; }
This will be checked by the compiler.
Advice: add const where appropriate.
class Date {
public:
Date(); // today's date
Date(int d, int m);
Date(int d, int m, int y);
...
};
Unlike basic types, objects are always initialized.
Date today; // uses default constructor
// note: no parentheses
Date christmas(25, 12);
Initialization as a copy of another object:
Date d1 = today;
Date d2(today); // equivalent
Assignment of objects performs a copy, member-by-member:
d1 = christmas;
These are the defaults;
later we shall see how these may be overridden.
Declaring object variables:
Date today;
Date christmas(25, 12);
In C++ (unlike Java) these variables contain objects
(not pointers/references to objects)
and they are already initialized.
Methods are invoked with a similar syntax to Java:
cout << today.get_day();
christmas.set_year(christmas.get_year() + 1);
except that in C++ today is an object.
Java uses dot for all qualification, while C++ has three different syntaxes:
| C++ | Java |
|---|---|
| object.field | (no equivalent) |
| pointer->field | reference.field |
| Class::field | Class.field |
| (no equivalent) | package.Class |
We can also use the constructor to make an object inside an expression:
cout << Date().get_day();
An object is created and initialized,
the method get_day() is called,
and the object is discarded.
(You can get a similar effect in Java with new,
but this relies on automatic garbage collection.)
Another example:
Date d;
...
d = Date(25, 12);
An object is created and initialized, copied into d,
and then discarded.
Members are initialized by constructors, not in their declarations.
class Date {
int day, month, year;
public:
Date() : day(current_day()),
month(current_month()),
year(current_year()) {}
Date(int d, int m, int y) :
day(d), month(m), year(y) {}
...
};
Initializers supply constructor arguments:
class Event {
Date when;
string what;
public:
Event(string name) : what(name) {}
Event(string name, int d, int m) :
what(name), when(d, m) {}
...
};
If no initializer is supplied, the default constructor is used.
int get_day() const { return day; }
C++ compilers treat these as inline functions:
they try to expand the bodies of the functions where they are called.
int get_day() const;
and give the full definition later, outside the class:
int Date::get_day() const { return day; }
Because this is outside the class, we must qualify the function name
with the class (Date::).
class Date {
private:
int day, month, year;
public:
Date();
Date(int d, int m);
Date(int d, int m, int y);
int get_day() const;
int get_month() const;
int get_year() const;
};
Note that this falls short of an ideal interface,
as all members (even private ones) must be included.
At a later point, outside of any class, we can define the methods. To indicate which class they belong to, they are qualified with ``Date::''.
Date::Date() : day(current_day()),
month(current_month()),
year(current_year()) {}
Date::Date(int d, int m, int y) :
day(d), month(m), year(y) {}
int Date::get_day() const { return day; }
Advice: place only the simplest method bodies in the class.
#include <cassert>
.
.
.
assert(position < size);