ENUMERATION ■ 309 ᮀ Definition An enumeration is a user-definable, integral type. An enumeration is defined using the enum keyword. A range of values and a name for these values are also defined at the same time. Example: enum Shape{ Line, Rectangle, Ellipse}; This statement defines the enumerated type Shape. The names quoted in the list iden- tify integral constants. Their values can be deduced from the list order. The first constant has a value of 0, and each subsequent constant has a value that is one higher than its predecessor. In the previous example, Line thus represents a value of 0, Rectangle a value of 1, and Ellipse a value of 2. A Shape type variable can only assume one of these values. Example: Shape shape = Rectangle; // Variable shape // switch(shape) // To evaluate shape { case Line: // etc. However, you can also define the values of the constants explicitly. Example: enum Bound { Lower = -100, Upper = 100}; You can leave out the type name, if you only need to define the constants. Example: enum { OFF, OUT=0, ON, IN=1 }; This statement defines the constants OFF and OUT, setting their value to 0, and the con- stants ON and IN with a value of 1. The values for OFF and ON are implicit. ᮀ Class-Specific Constants Enumeration can be used to define integral symbolic constants in a simple way. In con- trast to #define directives, which merely replace text strings, enum constants are part of a declaration and thus have a valid range. This allows you to define constants that are visible within a namespace or class only. The example on the opposite page shows the enumerated type State, which was defined within the Lights class. This means that the type and enum constant are only available for direct use within the class. The enumeration itself is declared as public, however, and access from outside the class is therefore possible. Example: if(Lights.getState() == Lights::red) // exercises 310 ■ CHAPTER 15 MEMBER OBJECTS AND STATIC MEMBERS Article( const Article& ); ■ EXERCISES Copy constructor of class Article The copy constructor creates a copy of an existing object.The parameter is thus a read-only reference to the object that needs to be copied.The copy constructor in the Article class is thus declared as follows: Declaration of copy constructor: The default copy constructor simply transfers the data members to the new object. The Member Class int string const Date Member Number Name Birthday //Possibly more information, such as an address, telephone number, Constructor with one parameter for each data member Access methods for each data member. The birthday is read-only. A method for formatted screen output of all data members Private Data Members Public Methods Type EXERCISES ■ 311 Exercise 1 In the first exercise of the last chapter you defined a simple class called Article.This involved using a global counter to log object creation and destruction. Improve and extend the Article class as follows: ■ Use a static data member instead of a global variable to count the current number of objects. ■ Declare a static access method called getCount()for the Article class. The method returns the current number of objects. ■ Define a copy constructor that also increments the object counter by 1 and issues a message.This ensures that the counter will always be accu- rate. Tip: Use member initializers. ■ Test the new version of the class.To do so, call the function test() by passing an article type object to the function. Exercise 2 A sports club needs a program to manage its members.Your task is to define and test a class called Member for this purpose. ■ Define the Member class using the data members shown opposite. Use the Date class defined in the last chapter for your definition. Since a member’s birthday will not change, the data member for birthdays must be defined as a const. Overload the constructor to allow for entering a date as an object as well as three values for day, month, and year. ■ Implement the necessary methods. ■ Test the new Member class by creating at least two objects with the data of your choice and calling the methods you defined. ■ Add a static member called ptrBoss to the class.This pointer indicates the member who has been appointed as chairperson. If no chairperson has been appointed, the pointer should point to NULL. ■ Additionally, define the static access methods getBoss() and setBoss(). Use a pointer to set and return the object in question. ■ Test the enhanced Member class by reading the number of an existing member, making the member the new chairperson and displaying the chairperson using getBoss(). 312 ■ CHAPTER 15 MEMBER OBJECTS AND STATIC MEMBERS Simulation of two traffic lights! Terminate this program with <Ctrl>+<C>! 1. Light 2. Light RED AMBER GREEN AMBER AMBER RED GREEN AMBER RED AMBER GREEN // . . . Sample output Hints for implementing the function wait() 1. The function time() is declared in the header file ctime. The call time(NULL) determines the number of seconds of type time_t since 1.1.1970, 0:0 hours.The type time_t is defined as long. 2. Instead of calling the function time() in a loop, you can use the function Sleep() for Windows or the function sleep() for Unix. These system calls are not standardized, yet they are much more effective because they send a process to sleep instead of using a waiting loop. EXERCISES ■ 313 Exercise 3 Create a program to simulate the signal positions for two sets of traffic lights at a junction. Use the class Lights as defined in this chapter for your program. ■ Each set of lights is switched through the phases red, amber, green, amber, red, and so on.You must ensure that one set of lights can be only in the amber or green state when the other set of lights is red. ■ The lights operate in an infinite loop that can be terminated by interrupt- ing the program.You can use the key combination <Ctrl>+<C> for DOS and Windows and the Interrupt key, i.e., normally the <Del> key, for UNIX. ■ The status of the lights is constant for a certain number of seconds. For example, the green phase can take 20 seconds and the amber phase 1 second.These values can be different for each set of lights. Define an auxiliary function inline void wait( int sec) The function returns after the stipulated number of seconds.To do so, you can call the standard function time() in a loop. Don’t forget to read the notes on the opposite page. solutions 314 ■ CHAPTER 15 MEMBER OBJECTS AND STATIC MEMBERS ■ SOLUTIONS Exercise 1 // // article.h // Defines a simple class - Article. // #ifndef _ARTICLE_H_ #define _ARTICLE_H_ #include <string> using namespace std; class Article { private: long nr; // Article number string name; // Article name double sp; // Sales price // Static data member: static int countObj; // Number of objects public: Article( long nr=0, const string& name="noname", double sp=0.0); // Copy constructor: Article( const Article& anArticle); ~Article(); void print(); // Access methods: const string& getName() const { return name; } long getNr() const { return nr; } double getSP() const { return sp; } static int getCount() { return countObj; } bool setName( const string& s) { if( s.size() < 1) // No empty Name return false; name = s; return true; } void setNr( long n) { nr = n; } void setSP(double v) { // No negative price sp = v > 0.0 ? v : 0.0; } }; #endif // _ARTICLE_ SOLUTIONS ■ 315 // // article.cpp // Methods of Article, which are not defined as inline. // Constructor and destructor output when called. // #include "article.h" // Definition of the class #include <iostream> #include <iomanip> using namespace std; // Defining the static data member: int Article::countObj = 0; // Number of objects // Defining the constructor and destructor: Article::Article( long nr, const string& name, double sp) { setNr(nr); setName(name); setSP(sp); ++countObj; cout << "An article \"" << name << "\" is created.\n" << "This is the " << countObj << ". article!" << endl; } // Defining the copy constructor: Article::Article( const Article& art) :nr(art.nr), name(art.name), sp(art.sp) { ++countObj; cout << "A copy of the article \"" << name << "\" is generated.\n" << "This is the " << countObj << ". article!" << endl; } Article::~Article() { cout << "The article \"" << name << "\" is destroyed.\n" << "There are still " << countObj << " articles!" << endl; } // The method print() outputs an article. void Article::print() { // As before! Compare to the solutions of chapter 14. } 316 ■ CHAPTER 15 MEMBER OBJECTS AND STATIC MEMBERS // // article_t.cpp // Tests the class Article including a copy constructor. // #include "article.h" // Definition of the class #include <iostream> #include <string> using namespace std; void test( Article a); // Prototype Article article1( 1111,"tent", 159.9); // Global int main() { cout << "\nThe first statement in main().\n" << endl; Article article2( 2222,"jogging shoes", 199.99); cout << "\nThe first call of test()." << endl; test(article1); // Passing by Value cout << "\nThe second call of test()." << endl; test(article2); // Passing by Value cout << "\nThe last statement in main().\n" << "\nThere are still " << Article::getCount() << " objects\n" << endl; return 0; } void test( Article a) // Calls the copy constructor { cout << "\nThe given object:" << endl; a.print(); static Article bike( 3333, "bicycle", 999.0); cout << "\nThe static object in function test():" << endl; bike.print(); cout << "\nThe last statement in function test()" << endl; } SOLUTIONS ■ 317 Exercise 2 The Date class from the last chapter ( see files Date.h and Date.cpp ) can be left unchanged. But it makes sense to define the function isLeapYear()as a static member function of class Date rather than globally. The other files: // // member.h // Defines the Member class containing a constant // and a static member. // #ifndef _MEMBER_H_ #define _MEMBER_H_ #include "Date.h" #include <string> using namespace std; class Member { private: int nr; // Member number string name; // Name const Date birth; // Birthday // more data static Member *ptrBoss; // Pointer to boss, // NULL = no boss. public: Member( long m_nr, const string& m_name, const Date& m_birth) : nr(m_nr), birth(m_birth) { if( !setName(m_name)) name = "Unknown"; } Member( long m_nr, const string& m_name, int day, int month, int year) : nr(m_nr), birth(day,month,year) { if( !setName(m_name)) name = "Unknown"; } int getNr() const { return nr; } const string& getName() const { return name; } const Date& getBirthday() const { return birth; } void setNr( int n) { nr = n; } 318 ■ CHAPTER 15 MEMBER OBJECTS AND STATIC MEMBERS bool setName( const string& s) { if( s.size() < 1) // No empty name return false; name = s; return true; } void display() const; // static methods: static Member* getBoss() { return ptrBoss; } static void setBoss( Member* ptrMem) { ptrBoss = ptrMem; } }; #endif // _MEMBER_H_ // // member.cpp // Members of class Member not defined inline. // #include "member.h" // Class definition #include <iostream> using namespace std; // Pointer to the boss: Member* Member::ptrBoss = NULL; void Member::display() const { string line( 50, '-'); cout << line << "\n Member number: " << nr << "\n Member: " << name << "\n Birthday " << birth.asString() << '\n' << line << endl; } . ENUMERATION ■ 309 ᮀ Definition An enumeration is a user-definable, integral type. An enumeration is defined using the enum keyword. A range of values and a name for these values are also defined at. 1, and Ellipse a value of 2. A Shape type variable can only assume one of these values. Example: Shape shape = Rectangle; // Variable shape // switch(shape) // To evaluate shape { case Line: // etc. However,. Constants Enumeration can be used to define integral symbolic constants in a simple way. In con- trast to #define directives, which merely replace text strings, enum constants are part of a declaration