Creating a class in C++ is similar to creating a struct. Class objects have members just like a structure, but instead of just data, they also have code or functions as members. The basic template is:
class ClassName { public: ClassName(); // Constructor ~ClassName(); //Destructor private: protected: };
Inside the public section of the above, the functions ClassName and ~ClassName are defined (like in a prototype). These are the constructor and destructor for this class. The constructor is called whenever an instance of a class is created, and the destructor is called when the instance is destroyed.
Note that the constructor and destructor are functions with the same name as the class, and have no return type. The destructor name is preceeded with the tilde (~), and never accepts an argument. The constructor may be overloaded. Constructors and destructors are not required, but are most commonly implemented.
In order to write any member function's body, it is usually done outside the definition, (the only difference between regular functions and members is the presence of ClassName:: as part of the name) in the following format:
ClassName::MemberFunction() { }
When a member function definition inside the class definition is followed by the const keyword, it means that the function will not change any of the (non-static) data members of that object. For instance:
class MDate { public: bool IsValid() const; private: int M, D, Y; };
In the above example, the IsValid member function of the MDate class has a const following its name and parameter list. This means that the code inside this function will not change any of the non-static data members, such as M, D, and Y.
Inline functions can be created within the class definition, without the inline keyword. The format requires the function's body to follow the member definition:
class Example { public: Example(); // Constructor ~Example (); // Destructor int IsExampleEmpty( void ) { return( IsEmpty ); }; // Automatic inline function private: int IsEmpty; };
The similarities between unions and structures, and classes in C++ goes a little further then might be expected. In C++, unions and classes may also include the protected, private, and public, as well as constructors, destructors, and other member functions. In fact, the struct is converted into a class by the C++ compiler. The only difference between these types is that union and struct members are public by default, where in a class the default is private.
Objects can be passed as regular variables (or references, or pointers ) to functions, but some care must taken.be taken. When an object is passed as a parameter, an exact copy of the object is made without invoking the object's constructor. On the other hand, the object's destructor is called for that copy when it is no longer needed. Some objects (especially ones where memory is allocated) will not work properly under these conditions.
In order to eliminate the problem describe above, a class must implement a copy constructor. A copy constructor is a special constructor that takes as an argument, a const reference to that same type. For example:
class Mobject { public: MObject(); // Regular constructor Mobject( const Mobject &Original ); // Note Original is not a required name. }
The copy constructor is called (instead of the default constructor) when an object is passed to a function, for auto-initialization, or when an object is returned from a function. It is not called during a normal assignment (you may right an overloaded operator to handle this). For example:
Foo( SomeObject ); // Copy constructor called to make a copy of SomeObject MObject A = B; // Copy ctor called for auto-initialization (B is an MObject ) A = B; // Copy constructor is NOT called.
You can place an enum definition within a class, and have the enum values follow the standard class access rules of private, public, and protected. Once defined, you access the enum as any other member, but for public members outside the class you must use the scope resolution operator:
#include <iostream> class MDate { public: enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; MDate() { M=0; D=0; Y=0; WeekDay=Sun; }; // Use 'Sun' constant value Day GetWeekDay( void ) { return( WeekDay ); }; // Use 'Day' data type private: Day WeekDay; // Use of Day data type char M, Y, D; }; void main( void ) { MDate Today; MDate::Day D; // Note scope resulotion operator D = Today.GetWeekDay(); if( D == MDate::Sun ) // Note scope resulotion operator cout << "All is well\n"; }
Static data members are members that only exist once, no matter how many instances of a class are created. These static members can be viewed almost like a global variable, except that they are accessed within an object. Remember that all objects (of the same or derived class) will share the same static member. You must declare the actual static variable outside the class definition, and inside. For example:
#include <iostream> enum Modes { off, on }; void TurnStreetLights( int Mode ) { cout << "Traffic lights turned " << (Mode ? "on":"off") << endl; } class Cars { public: Cars() { if( CarsOnRoad == 0 ) TurnStreetLights( on ); CarsOnRoad++; }; ~Cars() { if( --CarsOnRoad == 0 ) TurnStreetLights( off ); }; private: static int CarsOnRoad; // This defines CarsOnRoads as static }; int Cars::CarsOnRoad; // Note 2nd declaration, this is the actual variable void main( void ) { Cars Me; }
Functions within classes may also be static, and then they
only access other static functions.