Class

C++ will supply the following class methods if no definition (for class with pointer data members, remember to define them explicitly to handle memory allocation and deallocation):
  1. default constructor (constructor with no arguments), if no any constructor is defined (but for simple data type, there is no initialization of each data member to the default value of its associated type). If any constructor is defined, regardless of specific (have arguments) or default constructor, C++ will not generate default constructor automatically. So if default constructor is required, it need to be defined explicitly.
  2. destructor
  3. copy constructor
  4. assignment operator (operator=)

The words constructor and destructor are somewhat misleading in that these programmer-supplied functions neither construct nor destroy the objects of the class to which they are applied by the compiler automatically. The constructors of a class serve primarily to initialize the data members of the class object. The destructor primarily frees any resources acquired by the class object during its lifetime.


Constructor supplies default arguments for all data members can be used as default constructor.
class ClassName {
public:
  ClassName(double member1 = 0.0, int member2 = 0)
  : member1_(member1), member2_(member2) {
  }
  // or
  ClassName(double member1 = 0.0, int member2 = 0) {
    member1_ = member1;
    member2_ = member2;
  }

protected:
  double member1_;
  int member2_;
};

// usage in application
ClassName c1; // not c1()! c1() is not default constructor!
ClassName c2(-0.7, 2);
ClassName c3 = Account(3.5);
ClassName c4 = 10; // can only specify single (first) argument

If there is any constrcutor taken argument, default constructor need to be provided explicitly. Although there is no appropriate default values for some classes to allow default constructor, in practice it is almost always necessary to provide beacuse the container classes (e.g. vector), array and dynamic array require default constructor to initialize their elements. In this case, the best is to initialize the object to indicate that it is not yet initialized with a valid set of values (NULL for pointer, 0 for number). Then need to program checks within all member functions to guarantee the integrity of the class object prior to its use (user must explicitly set valid value through modify member function).

The difference of member initialization list and assignment of the data members within the body of the constructor is the former is an initialization while the later is an assignment (initialization is done using default constructor). For efficiency, member class object (non-built-in data type) should always be initialized in the member initialization list, or no need to explicitly initialize (use default constructor).

const and reference data members must always be initialized in the member initialization list; otherwise, a compile-time error results. The order of initialization is determined by the class declaration order of the members, not the order of member initialization list. Mis-understand this can lead to difficult-to-uncover error when using one class member to intialize another. It is recommended to list members in an initialization list in the order in which they are declare.


An object's initialization occurs when it is given a value for the very first time. For objects of classes or structs with constructors, initialization is always accomplished by calling a constructor. This is quite different from object assignment, which occurs when an object that is already initialized is given a new value:
string s1; // initialization
string s2("Hello"); // initialization
string s3 = s2; // initialization
s1 = s3; // assignment

From a purely operational point of view, the difference between initialization and assignment is that the former is performed by a constructor while the latter is performed by operator=. In other words, the two processes correspond to different function calls.

The reason for the distinction is that the two kinds of functions must worry about different things. Constructors usually have to check their arguments for validity, whereas most assignment operators can take it for granted that their argument is legitimate (because it has already been constructed). On the other hand, the target of an assignment, unlike an object undergoing construction, may already have resources allocated to it. These resources typically must be released before the new resources can be assigned. Frequently, one of these resources is memory. Before an assignment operator can allocate memory for a new value, it must first deallocate the memory that was allocated for the old value.


Pass-by-value means "call the copy constructor."

C++ provides a default copy constructor that perform a bitwise copy of each of the data members of the class. But when a class contain pointer data member to dynamic allocated memory, copying the bits of pointer does not copy the allocated memory, so need to override it. Argument must be passed by reference, not for efficiency (avoid calling constructor/destructor), but also to avoid recursive copy constructor call! This may also needed when bitwise copy is inappropriate for the correct behavior of the class.
ClassName(const ClassName& original);

// usage in application
ClassName c2(c1), c4 = c3;	// just like: int i(-4), j = i;
ClassName c5 = Function(c1);	// pass/return by value

Passing or returning an object by value is inefficient for two reasons
  1. Object passed or returned by value has sizeof ClassName bytes, thus an inefficient use of storage to copy objects whose size in bytes is large.
  2. An object is copied through a call to the copy constructor, which means that passing or returning an object by value involves a method call. If the copy constructor does a large amount of processing, the process may be very time-consuming.

The call to the copy constructor may be not obvious from the source code when it is generated by the compiler. Accordingly, it is easy for the programmer to forget the overhead associated with passing or returning by value. The class designer can disable passing or returning by value for functions outside the class by defining it as private.


Same as constructor, destructor does not specify a return type or return a value (not even void). But destructor also does not take arguments and cannot be overloaded. By default compiler will generate no-operation destructor if omitted.
~ClassName(void);

A convert constructor can be used as an alternative to function overloading. Suppose that function f expects a String object as an argument void f(String s); but that the programmer forgets and invokes it with a string constant such as f("Turandot");. If the String class has this convert constructor
String(const char s[]); // convert constructor
then the compiler invokes the convert constructor for implicit type conversion. The conversion is implicit in that the compiler performs it; the programmer does not need to provide an explicit cast. However, implicit type conversions may lead to unforeseen, very subtle and hard to detect error. The keyword explicit, which occurs in a convert constructor's declaration, may be used to disable implicit type conversions through a convert constructor. It is generally required only for constructor taking one argument.
class String {
public:
  explicit String(const char s[]);
};

If same portion of code is use in several place in member functions, keep the code in one protected/ private helper function and each member function call it. This ease maintainance.


Since copy constructor is similar to assignment operator, initialize to default value and then let copy constructor call operator= will simplify maintainance. Moreover, it's beneficial to group the default initilization and cleaning codes as protected constructor helper function. The downside is less efficient as invoke default constructor and default initilization before real assignment. Similarly, default initilization is not required by destructor as memory has been deallocated, but better included at the end of cleaning codes to avoid bug. This is the efficiency-maintenance tradeoff.
class ClassName {
public:
  ClassName(void) {
    Initialize();
  }
  ~ClassName(void) {
    Clean();
  }
  ClassName(const ClassName& original) {
    Initialize();
    (*this) = original;	// use operator=()
  }

protected:
  int member1_;
  double *member2_;

  Initialize(void) {
    member1_ = 0;
    member2_ = NULL;
  }
  Clean(void) {
    if ( member2_ != NULL )
      delete member2_;
    Initialize();
  }
};

To prevent any member function (e.g. copy constructor and assignment operator because not implemented yet), declare it to be private member function and do not provide a definition of either. In this way, using it results in compile-time error because cannot access private member of the class or link-time error (no definition) if using it in the class.
class ClassName {
private:
  ClassName(const ClassName& original);
  ClassName& operator=(const ClassName& original);
};

Protected constrcutor is also commonly declared to indicate that it is intended to be invoked only when the class serves as a base class within an inheritance hierarchy and not as an object to be manipulated directly within the application.


If member function definition is simple, include it in class declaration so that it will automatically inline. Data-extraction function (return member variable's value) and modify member function (to modify data member) should be defined within the class itself. Why data-extraction and modify member function?
class ClassName {
public:
  member1type GetMember1(void) const { return member1_; }
  member2type GetMember2(void) const { return member2_; }
  void SetMember1(member1type member1) { member1_ = member1; }
  void SetMember2(member2type member2) { member2_ = member2; }

protected:
  member1type member1_;
  member2type member2_;
};

// usage in application
c2.SetMember2(c1.GetMember1());

Avoid returning "handles" of class internal data through through data-extraction function by directly passing pointer or reference. For a const object of this class, this may cause its content to be modified inadvertently.
class String {
public:
  String(const char *str);
  operator char *() const { return str_; }
  char& operator[](int index) const { return str_[index]; }

protected:
  char *str_;
};

const String cs("Hello World");
char *str = cs; // call cs.operator char*()
strcpy(str, "Hi World!"); // modify what str points to!
String s = "I'm not constant";
s[0] = 'x'; // OK
cs[0] = 'x'; // modify const string without complaint!
If the intent is not allow user to change data member directly, no matter it is const or not, return a const pointer to prevent user change the content of memory pointed after get it.
class ClassName {
public:
  const member1type* GetMember1() const {
    return (const member1type*)member1_;
  }

protected:
  member1type *member1_;
};

// usage in application
ClassName c1;
member1type *pc1 = c1.GetMember1(); // error: cannot convert const* to *
const member1type *pc2 = c1.GetMember1(); // OK
cout << c1.GetMember1() << endl; // OK
If wish to allow user change data member directly if it is not const object, don't declare the member function const.
class ClassName {
public:
  member1type* GetMember1(void) {
    return member1_;
  }

protected:
  member1type *member1_;
};

// usage in application
ClassName c1;
member1type *pc1 = c1.GetMember1(); // OK
const ClassName cc1;
const member1type *pc2 = cc1.GetMember1(); // error: member function not const
cout << c1.GetMember1() << endl; // OK

Or provide two member functions serve for non-const and const object, such as indexing operator.

Even return const class internal data handles is ill-advised, not only it violates abstraction, but it can cause dangling handle issue on compiler-generated temporary object.
class String {
public:
  String(const char *str);
  operator const char *() const { return str_; }

protected:
  char *str_;
};

String GetStr(void)
{
    return "Hello World";
}                

const char *pc = GetStr(); // pc points to temporary String object
// temporary String object destroyed
cout << pc; // result undefined

Member function can declare inline either during declaration in class definition or its definition. However, since inline functions must be defined in every text file in which they are called, inline member function that is not defined in class header file must be placed in class definition.


Constant class object can only access constant member function, that has const keyword is placed between the parameter list and the body of the member function to mark data member as read only. The keyword must be specified in both its declaration and its definition. Constructors and destructors are exceptions in that, even though they are never constant member functions, they can be called by constant class object. Its const-ness start from the time its construction completes to the time its destruction starts.

Constant member function can be overloaded with a non-const member function that has the same parameter list. The const-ness of the class object determines which function is invoked.

If the class contains pointer, the pointer cannot be modified but the object which the pointer refer can be modified within a constant member function.
class ClassName {
public:
  void Bad(const string& str) const
private:
  char *text_;
};

void ClassName::Bad(const string& str) const
{
  text_ = str.c_str(); // error: text_ cannot be modified
  for (int i=0; i<str.size(); i++)
    text_[i] = str[i]; // bad style but not an error
}

There are two prevailing notions of constness:

  1. bitwise constness - a member function is const if and only if it doesn't modify any of the object's data members (excluding those that are static). The nice thing about bitwise constness is that it is easy to detect violations: compilers just look for assignments to data members. It is C++'s definition of constness.
  2. conceptual constness - a const member function might modify some of the bits in the object on which it's invoked, but only in ways that are undetectable by clients. The solution of this kind of bitwise-constness-is-not-quite-what-I-had-in-mind problem is mutable data member.
Mutable data member is member that never constant, even when it is data member of constant object. The purpose of mutable member is allowed modification in a const member function.
class Screen {
public:
  inline void Move(int r, int c) const;
private:
  string screen_;
  mutable string::size_type cursor_; // mutable member
  short width_;
  short height_;
};

void Screen::Move(int r, int c) const
{
 if (CheckRange(r, c))
 {
   int row = (r-1) * width_;
   cursor_ = row + c - 1; // modify cursor_
 }
}

This is logical, because modifying cursor_ is necessary to inspect the content of Screen object and does not modify the content of the Screen itself.


A friend may be a namespace function, a member function of another previously defined class or an entire class. In making one class a friend, all the member functions of the friend class are given access to the nonpublic members of the class granting friendship.

Since friends are not members of the class granting friendship, they are not affected by the public, private or protected section in which they are declared within the class body.


Guideline to implement operation as member function or friend:
Default assignment member function is for copy of info pointed to ("deep" copy), not copy of address (bitwise "shallow" copy). Deep copy for dynamic memory allocation
  1. deallocate old info if necessary to avoid memory leak
  2. new allocation and assertion of success
  3. copy info over
Assignment member function must return a reference to itself for chain assignment c1 = c2 = c3; (evaluated as c1.operator=(c2.operator(c3));). Self-test is a must not only for speed reason, but also avoid aliasing (having two or more names for the same underlying object) and subsequently catastrophic delete (if pointer data member dynamically allocate memory) in self-assignment situations.
ClassName& Classname::operator=(const ClassName& original)
{
  if (this == &original) return *this; // self-test

  member1_ = original.member1_; // copy scalar member
  // copy other data member ...

  return *this;	// return this object
}

ClassName& c1 = c2, *pc3 = &c3;
*pc3 = c3; // self-assignment
c2 = c1;   // or vice versa
The problems of aliasing and object identity are hardly confined to assignment member function. In the presence of references and pointers, any two names for objects of compatible types may in fact refer to the same object. Since it can crop up in any number of nefarious disguises, need to take it into account any time write a function (want to self-test or not?).
class BaseName {
  void mf1(BaseName& rb); // rb and *this could be the same
};

void f1(BaseName& rb1, BaseName& rb2); // rb1 and rb2 could be the same

class DerivedName: public BaseName {
  void mf2(BaseName& rb); // rb and *this could be the same
};

int f2(DerivedName& rd, BaseName& rb); // rd and rb could be the same

Indexing operation need 2 operators to serve non-constant as well as constant object.
char& basic_string::operator[](int position); // can be rvalue or lvalue
const char& basic_string::operator[](int position) const; // rvalue only

Similarly, IO operator return its stream reference parameter to allow chaining cout << c1 << c2;(evaluated as operator<<(operator<<(cout,c1),c2);).
friend ostream& operator<<(ostream& outStream, const ClassName& c)
{
  // format and output statements ...
  return outStream;
}
friend istream& operator>>(istream& inStream, ClassName& c);
friend fstream& operator<<(fstream& outStream, const ClassName& c);
friend fstream& operator>>(fstream& inStream, ClassName& c);
Generally to allow chaining operation need to return a reference to itself. This is suitable to member function that originally void.
Screen& Screen::Clear(const char bkground = ' ')
{
 // ...
 return *this;
}
//...

// usage in application
screen1.Clear().Move(2, 2).Set('*').Display();

Arithmatic operation
const ClassName operator+(const ClassName& lhs, const ClassName& rhs)
{
  ClassName result;
  // addition statements ...
  return (const ClassName)result;	// will call copy constructor
}
const ClassName operator-(const ClassName& lhs, const ClassName& rhs);
const ClassName operator*(const ClassName& lhs, const ClassName& rhs);
const ClassName operator/(const ClassName& lhs, const ClassName& rhs);
C++ compiler distinguish prefix and postfix increment and decrement operation by
ClassName& operator++(void);		// prefix, ++c
const ClassName operator++(int);	// postfix c++
ClassName& operator--(void);		// --c
const ClassName operator--(int);	// c--

ClassName& operator+=(int);
ClassName& operator-=(int);
Prefix increment should be implemented as "increment and fetch" while postfix form as "fetch and increment".
// prefix form
LargeInt& LargeInt::operator++()
{
  *this += 1; // increment
  return *this; // fetch
}

// postfix form
const LargeInt LargeInt::operator++(int) // no use of parameter
{
  LargeInt oldValue = *this; // fetch
  ++(*this); // increment, implemented in terms of their prefix
  return oldValue; // return what was fetche
}

This indicates that when dealing with user-defined types, prefix form is preferable because it is inherently more efficient.


Return by value is neccessary as returned reference of member function's local variable will be undefined. But for large and complex class may be unacceptably expensive. One solution is replace operator overloading function with named function taking extra reference parameter to store the result, but the class can no longer be used with operator syntax.
void Add(ClassName& result, const ClassName& lhs, const ClassName& rhs)
{
  // addition statements ...
}

Some compiler could recognize the return of the class object and provide the return value transformation, eliminating both the return by value of the class object and the need to invoke the class copy constructor.

ClassName Function(parametertype parameter)
{
  ClassName result;
  // ...
  return result;
}
// transform into
void Function(Classname& result, parametertype parameter)
{
  // result = ...
}
To trigger it, the class object returned at each return point within the function must be the same named object.

Initialization of a class object ClassName c3 = c1 + c2; is always more efficient than its assignment ClassName c3; c3 = c1 + c2;. The reason is ClassName c3 = opeartor+(c1, c2); can be safely transformed into ClassName c3; operator+(c3, c1, c2); but not safe to transform ClassName c3; c3 = opeartor+(c1, c2); into operator+(c3, c1, c2);. The problem is the transformed function requires the object passed to it to represent raw storage, so can apply the constructor that had been applied to the named local object. If the object being passed in has already been constructed, then it is potentially semantically disastrous to construct it a second time. Instead, the compiler will create raw storage in the form of temporary class object to pass to the function and destruct temporary object when it returns.


For class with pointer data members, What should operator== mean?

This is the object identity issue: what it means for two objects to be "the same." The first definition is more common, probably because it is easy to implement and the computation is fast, neither of which is always true when object identity is based on values (Recall the self-test in copy constructor and assignment member function). Choose appropriate definition. Generally identity test does not require operator== to compare in object level, just compare their addresses. If it is treated as relational operator, then it will be equality test.

// relational operation
bool operator==(const ClassName& rhs);
bool operator!=(const ClassName& rhs);
bool operator<(const ClassName& rhs);
bool operator<=(const ClassName& rhs);
bool operator>(const ClassName& rhs);
bool operator>=(const ClassName& rhs);
All the relational operators can be implemented using operator== and operator<.


Static data member and member function is class member (belong to the class as a whole), as opposed to object member (belong to individual objects in the class). It can be declared inside the class declaration, but still need to define globally. As with any global object, only one static data member definition can be provided in a program. This means that static data member initialization should not be placed in header files, but rather in the files containing definitions of the class non-inline member functions.

Any member function can access static data member, but static member function can only access static data members, not non-static data members (as it don't have this pointer). Its benefit is no need class member access operator to call the function (since none of non-static data members are ever accessed or modified, it is really irrelavant). Static member function can also be accessed even if no class objects are ever declared.

class ClassName {
public:
  static unsigned GetN(void) const { return n_; } // inline
  static static2type GetStatic2(void);
private:
  static unsigned n_; // count of ClassName objects
  static static2type static2_;
};

unsigned ClassName::n_ = 10;
static2type ClassName::static2_;

static2type ClassName::GetStatic2(void) { // non-inline
  return static2_;
}
If the static data member or member function is public, it can be accessed through either class objects or directly.
ClassName c1;

c1.GetN();
// or
ClassName::GetN();

unsigned n1 = c1.n_;
// or
unsigned n2 = ClassName::n_;

Static local variable in member function is a underlying cell shared by all class objects when they invoke the function. So it is actually similar to static data members except it is in function scope.


Operator new and delete are static member fnctions without the need for the programmer to declare them static explicitly. The reason for this is that these operators are invoked either before the class object is constructed (operator new) or after it has been destroyed (operator delete). Operator delete has two forms but only one can be declared. To allocate array of class objects need operator new[] and delete[].
void* operator new(size_t size); // size in bytes
void* operator new[](size_t size); // size in bytes
void* operator new(size_t size, ClassName *p); // for placement new
void* operator new[](size_t size, ClassName *p); // for placement new[]

// either
void operator delete(void *p);
void operator delete[](void *p);
// or
void operator delete(void *p, size_t size);
void operator delete[](void *p, size_t size);

// for exception handling of executing new expression
void operator delete(void *p, ClassName *p);
void operator delete[](void *p, ClassName *p);

A new expression that creates an array first calls the operator new[] to allocate the storage and then calls the default constructor to initialize iteratively every element of the array; a delete expression that deletes an array first calls the class destructor to destroy iteratively every element of the array and then calls the operator delete[] to deallocate the storage.

Placement new (need to #include <new>) is used to construct object from already pre-allocated memory. It allows to invoke constructor directly, useful for applications using shared memory or memory-mapped I/O, because objects in such applications must be placed at specific addresses or in memory allocated by special routines. The downside is, need to manually call destructor when want them to go out of existence.
// allocate enough raw memory for an array of 10 ClassName objects
void *buffer = operator new[](10 * sizeof(ClassName));
// cArray point to it so it can be treated as an ClassName array
ClassName *cArray = static_cast<ClassName*>(buffer);
// initialize the ClassName objects using placement new
for (int i=0; i<10; ++i)
  new (&cArray[i]) ClassName(IDNum[i]);

// ...

for (int i=9; i>=0; --i)
  cArray[i].~ClassName();
// deallocate the raw memory
operator delete[](buffer);

Operator-> and *(dereference) often overloaded by smart pointer.


Conversion function takes the general form operator type();, where type is either built-in type, class type or typedef name (not array or function type). Conversion function must be member function. Its declaration must not specify a return type nor parameter list. For example, operator int() { return static_cast<int>(val); }. operator cchar is const char* conversion function. Another way is use single-argument constructor as convert constructor.
class B; // forward declaration for class B

class A {
public:
  A(const B&); // an A can be constructed from a B
};

class B {
public:
  operator A(void) const; // a B can be converted to an A
};

// usage in application
void f(const A&);
B b;
f(b); // compiler error: ambiguous

If the target of the conversion (e.g. double) does not match the type of the conversion function (e.g. int) exactly, conversion function can still be invoked if the target type can be reached through a standard conversion sequence. User-defined conversions are applied implicitly by the compiler. This may cause many viable functions during member function overload resolution.

Conversion operator can lead to the wrong function being called. The solution is to replace it with equivalent functions that don't have the syntactically magic names, like B::toA(void). Convert constructor is even worse, as it quietly creates new object result of mistyping function (can be operator overloading function) parameter. That is why explicit keyword is introduced.


There are two kind of constant data member:
  1. static: Same to all instance of the class. For integral type generally use anonymous enum (the enum hack should not be used anymore), but in fact can use static data member declaration style and C++ standard support initialization within the class body with a constant integral value (but not Visual C++). Even this case, the constant integral data member must still be defined outside the class body and must not specify an initial value (as already initialized).

  2. non-static: Each instance has different value. There is a tricky way to define it using constructor header.
#include <string>
using namespace std;
class ClassName {
public:
  ClassName(void)
  : STR2_("FLOATING") {
    // other initialization
  }
  ClassName(const string& str1)
  : STR2_(str1) {
    // other initialization
  }
  string GetStr1(void) { // no need const string, but must const string&
    return STR2_;
  }
private:
  enum { ONE = 1 };
  static const int TWO;
  static const short THREE = 3;	// VC++ not support
  static const string STR1_;
  const string STR2_;
};

// in implementation file
const int ClassName::TWO = 2;
const short ClassName::THREE; // definition needed, but no initialization
const string ClassName::STR1_ = "FLOATING2";

Why do these inconvenient restrictions exist? A class is typically declared in a header file and a header file is typically included into many translation units. To avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.


The size of an empty class is not zero to ensure that the addresses of two different objects will be different. For the same reason, new always returns pointers to distinct objects.
class Empty { };

int main()
{
  Empty a, b;
  if (&a == &b)
    cout << "impossible: report error to compiler supplier";
  Empty* p1 = new Empty;
  Empty* p2 = new Empty;
  if (p1 == p2)
    cout << "impossible: report error to compiler supplier";
  delete p1;
  delete p2;
  return 0;
}

In C++ class representation, although each object has its own copy of the class data members, there exists only one copy of each class member function. This save memory. Each member function contain this pointer that addresses the object for which the member function is called. Its type in non-const member function is pointer to the class type, pointer to const class type in constant member function and pointer to volatile class type in a volatile member function. When an object call the member function, this points to its data members.
ClassName * const this; // for non-const member function
const ClassName * const this; // for const member function

c1.SetMember1(member1);
// is translate to
SetMember1(&c1, member1) { this->member1_ = member1; }

To understand what and why have nested class (nested in another class) and local class (defined inside a function body), think them as struct (struct and class is the same in C++) only used inside a class and function. They normally simple (basically data structure and some helper function) and mostly public members (easy for its host to access). Typical example is list node struct/ class inside list class.


The rule of thumb of designing simple interface is only data or functions that are taking any responsibility for maintaining the invariant should be defined as class. The invariant is the valid state of the member variables that need to keep track. Just using the data or functions, but not defending the invariant, doesn't need to be in the class, better be struct or function built on top of existing class.

If the class is full of Set and Get member functions, it seem like an unnecessary layer of abstraction to the data. If there is too many dynamic cast casting from base classes to derived classes, this indicates that there might be too much class hierarchies.

The way the whole thing is conceived is that the constructor establishes the environment for the member functions to operate in, in other words, the constructor establishes the invariant. And since to establish the invariant often have to acquire resources, the destructor will pull down the operating environment and release any resources required.

For example, in vector, size and elements that it hold much be matched. If the function changes the size of a vector, then it need to changes the number of elements stored and move the elements. There must be a member function for that. But given efficient element access, find function for searching in a vector is best provided as a non-member.

In Date class, functions such as find_next_Sunday should not be member function, else the class will be crowded making hard to change the data layout.

Index