CSCE 121 Chapter 9
« previous | Wednesday, September 22, 2010 | next »
Classes
User-defined type that represents a noun concept
Data members in a class can be manipulated through function members
Example:
class X { // class name is X
public: // accessible by all
int m; // data member
int mf(int v) { int old = m; m = v; return old; } // function member
private: // only accessible by functions in this class
// functions
// types
// data
};
int main() {
X var;
var.m = 7;
var.mf(9); // returns 7;
}
Data is often best kept private, so class members are private by default.
Structs
Struct is a class where members are public by default
struct Date {
int y, m, d;
}
Date my_birthday;
my_birthday.y = 12;
my_birthday.m = 27;
my_birthday.d = 1991; // oops! invalid date, but it's perfectly fine.
Helper Functions
struct Date {
int y, m, d;
// helper functions
Date (Date& dd, int y, int m, int d); // check for valid date
void add_day(int n);
}
Date my_birthday; // This now throws an error because it does not initialize my_birthday
Date my_day(1991, 12, 27); // ok
my_day.add_day(5); // should be January 1, 1992, but my_day.m is now 14
The notion of a "valid date" means that values have to be valid. Rules for what define "valid" values are called invariants.
If we can't think of a good invariant, we should probably use a struct
When defining a class, it's always a good idea to declare the class first, then define the details later.
// date.h
class Date {
public:
class Invalid {};
Date(int y, int m, int d);
void add_day(int n);
int month();
int day();
int year();
private:
int y, m, d;
bool check(int y, int m, int d);
};
// date.cpp
Date::Date(int yy, int mm, int dd) : y(yy), m(mm), d(dd) {
if (!check(y, m, d)) throw Invalid();
}; // is the ';' necessary?
Date::add_day(int n) { /* ... */ };
Public/Private Debate
Segregation of public and private members keeps the code clean. Declare invariants
Enumerations
Declared enum; a very simple type with a set of values.
enum Month {
jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};
Numerically indexed from zero by default, but can be changed (see code above). Cannot assign by Month m = 7.
Can assign without type declaration to define constants:
enum { red, blue };
int color = red;
Const
class Date {
public:
// ...
int day() const { return d; } // const member function not allowed to modify anything
void add_day(int); // non-const member is allowed to modify class data member
// ...
};
Date d(2000, Date::jan, 20);
const Date cd(2001, Date::feb, 21); // not allowed to change after initialized
cout << d.day() << " - " << cd.day() << endl; // okay to get const member on const variable
d.add_day(1); // okay
cd.add_day(1); // not okay; cd is a const, and add_day is not a const member function
Classes (cont'd)
- Minimal: as small as possible
- Complete: and no smaller
- Type Safe: beware of confusing argument orders
- const Correct: use for get() functions
- Default constructor when no constructor is declared inits to nothing
- Copy constructor (default: copy member)
- Copy assignment (default: copy members)
Date d; // default
Date d2 = d; // copy constructor
d = d2; // copy assignment
Interfaces and "Helper Functions"
- Keep it simple
Sometimes we need extra "helper functions" outside the class scope (non-member functions) like operators:
- ==, !=, next_weekday(), next_Sunday()
Operator Overloading
Date next_Sunday(const Date& d) { /* ... */ }
bool operator==(const Date& a, const Date& b) {
return a.year() == b.year() && a.month() == b.month() && a.day() == b.day();
}
bool operator!=(const Date& a, const Date& b) { return !(a==b); }
Almost all C++ operators can be defined with the operator##() function, where ## is the operator (+, -, *, /, ++, !=, etc.)