Presentation is loading. Please wait.

Presentation is loading. Please wait.

Classes: Part 2.

Similar presentations


Presentation on theme: "Classes: Part 2."— Presentation transcript:

1 Classes: Part 2

2 Static class members

3 Static vs. Dynamic Variables
Generally speaking: ‘static’ is meant to be ‘non-dynamic’ Global and local variables Locals are automatic variables from the ‘stack’ of the memory, therefore called ‘static’ Dynamic variables are from the ‘heap’ of the memory. In C and C++, ‘static’ has a ‘reserved’ specific meaning: ‘static’ variables are ‘global’ with the file scope 3

4 Static variables in C and C++
Static variables are put somewhere ‘permanently’ or ‘globally’ in memory The static variable ‘s’ can only be accessed within the function but it is not deleted with the function A ‘local’ static variable is a ‘global’ variable for the function, not the others. int f(){ static int s = 0; return s++; } int main() { cout << f() << endl; Output: 1 2 Don’t do it unless you have a good reason! 4

5 A static variable is shared by all objects of the class!
Static class members A variable that is part of a class, but not part of an object of that class, is called a static member. There is exactly one copy of a static member per class, instead of one copy per object for non-static members like a kind of global variables but they have class scope (outside the class, they cannot be accessed) A static variable is shared by all objects of the class! 5

6 Members of the class, not that of the objects
A a,b,c,d, … ; a.l b.l c.l d.l (multiple copies) a.g = b.g = c.g = d.g = … = A::g (one copy) class A { int l; static int g; } A::g Members of the class, not that of the objects member data, non-static, so far belong to ‘objects’ or ‘instances’ of the class member data, static, are ‘variables’ of the class, not the objects.

7 Public static class member Private static class member
To access a public static class member when no objects of the class exist: A::g Also accessible through any object of that class a.g Private ‘static’ members are still only to be accessed by member functions! 7

8 Initialization: primitive types
By default, a static class member is initialized to zero. class A { Public: static int g; } int A::g = 1; int main() { A::g = 100; Initialization, has to go with the file of the class

9 Constant static class members
class A { Public: const static int c = 100; } a const static class member can be initialized in the class defintion. class A { Public: const static int c; } const int A::c = 1; Or , has to go with the file of the class

10 Constant static member
class F { public: static int getcount(); private: const static int count = 2; }; int F::getcount() { cout << count; } int main() { F::getcount(); // print out 2 10

11 It is only possible for initialization, but not an access!
class F { public: static int getcount(); // static member function cannot have `const' method qualifier private: const static int count; }; // initialization of constant static variable: must be here; not in main() const int F::count = 2; int F::getcount() { cout << count; } int main() { F::getcount(); // print out 2 cout << F::count; // wrong as 'const int F::count' is private return 0; It is only possible for initialization, but not an access! 11

12 A static member of a class type (not a primitive type) is not initialized, but constructed by the default-value constructor 12

13 Static member functions
Declare a member function static It cannot access non-static data members or non-static member functions of the class (because the object may not exist when the function is called) (A static member function does not have a this pointer) static data members and static member functions exist independently of any objects of a class, i.e., when a static member function is called, there might not be any objects of its class in memory 13

14 Example (SEmployee.h) class Employee { public: Employee(const char *const, const char *const); ~Employee(); const char* getFirstName() const; const char* getLastName() const; static int getCount(); private: char* firstName; char* lastName; static int count; // number of objects instantiated }; Static data member keeps track of number of Employee objects that currently exist; Static member function may be called even the object does not exist. 14

15 Even static count is private!
class Employee { public: Employee(const char *const, const char *const); ~Employee(); const char* getFirstName() const; const char* getLastName() const; static int getCount(); private: char* firstName; char* lastName; static int count; // number of objects instantiated }; // define and initialize static data member at file scope int Employee::count = 0; // cannot include keyword static int Employee::getCount() { return count; } Even static count is private! static data member is defined and initialized at file scope in the .cpp file static member function can access only static data, because the function might be called when no objects exists 15

16 Employee::Employee(const char *const first, const char *const last)
{ firstName = new char[ strlen( first ) + 1 ]; strcpy(firstName, first); lastName = new char[ strlen( last ) + 1 ]; strcpy( lastName, last ); count++; cout << "Employee constructor for " << firstName << ' ' << lastName << " called." << endl; } Non-static member function (e.g., constructor) can modify the class’s static data members 16

17 Remember to deallocate memory reserved for arrays
Employee::~Employee() { cout << "~Employee() called for " << firstName << ' ' << lastName << endl; delete[] firstName; delete[] lastName; count--; } Remember to deallocate memory reserved for arrays 17

18 static.cpp (1/2) cout << "Number of employees before instantiation of any objects is " << Employee::getCount() << endl; Employee* e1Ptr = new Employee( "Susan", "Baker" ); Employee* e2Ptr = new Employee( "Robert", "Jones" ); cout << "Number of employees after objects are instantiated is “ << e1Ptr->getCount(); Calling static member function using class name and binary scope resolution operator Calling a static member function through a pointer to an object returns the value of the static variable Same as getting the value of Employee::count or calling Employee::getCount() 18

19 cout << "\n\nEmployee 1: " << e1Ptr->getFirstName() << " "
<< e1Ptr->getLastName() << "\nEmployee 2: " << e2Ptr->getFirstName() << " " << e2Ptr->getLastName() << "\n\n"; delete e1Ptr; e1Ptr = 0; // e1Ptr = NULL; delete e2Ptr; e2Ptr = 0; cout << "Number of employees after objects are deleted is " << Employee::getCount() << endl; Even when no object exists, we can still call static member function getCount() 19

20 static.cpp Sample Output
Number of employees before instantiation of any objects is 0 Employee constructor for Susan Baker called. Employee constructor for Robert Jones called. Number of employees after objects are instantiated is 2 (same as calling Employee::getCount() = 2) Employee 1: Susan Baker Employee 2: Robert Jones ~Employee() called for Susan Baker ~Employee() called for Robert Jones Number of employees after objects are deleted is 0 20

21 Type conversions

22 Assignments of different classes
class T { ... public: T& operator=(const T&); T& operator=(const X&); T& operator=(const int); }; main() { T a,b; X x,y; b = a; // b.operator=(a) a = x; // a.operator=(x) a = 10; // a.operator=(10) }

23 Constructors from a different class
class T { ... public: T(const X& x); }; main() { X x,y; T c(x), d(y); }

24 The compilor will do the convertion
If not defined, automatic converstion … class A { public: A (int i); A& operator=(const A&); // A& operator=(int i) }; A a; A temporary(10); // or temporary = 10; a = temporary; A a; a = 10; The compilor will do the convertion

25 More generally, for any classes:
class A {}; class B { public: B (A a) {}; B& operator=(const B&); // B& operator=(const A&); }; A a; B b; b = a; // B temp(a); // b.operator=(temp);

26 The compile will do if no ‘explicit’!
‘explicit’ constructors (not explicit-value constructors) A a; A temporary(10); // or temporary = 10; a = temporary; A a; a = 10; No, types do not match! The compile will do if no ‘explicit’! class A { public: explicit A(int i); }

27 Avoid implicit type conversion
Example: Avoid implicit type conversion class IntCell { public: explicit IntCell(int initialValue = 0) : storedValue(initialValue) {} int read( ) const {return storedValue;} void write(int x) {storedValue = x;} private: int storedValue; }

28 Try to implicitly call IntCell (x), which is ‘explicit’!
main(){ int x = 4; // same as int x(4); IntCell z(5); // now 5 (call explicit-value constructor) IntCell t; // now 0 (call default constructor) IntCell u = IntCell(x); // now 4 (call explicit constructor) IntCell y = x; // invalid implicit conversion: y = IntCell(x) } Try to implicitly call IntCell (x), which is ‘explicit’! If no ‘explicit’ keywork, IntCell y = x; is OK.

29 Recommendations Make all one-parameter constructors ‘explicit’ to avoid behind-the-scene type conversions. Keep ‘strong typing’ is desirable, avoid hard-to-find bugs

30 Constructors with initializers

31 How to initialize a ‘const’ private member?
class Increment { public: Increment(int c=0, int i=1); void addIncrement(){ count += increment; } private: int count; const int increment; }; It is not ‘static’, so ‘the const increment’ is different for each object! It has to be initialized with a new mechanism  using a member initializer 31

32 Increment::Increment(int c, int i) : count(c), increment(i) { }
(See Increment.h, Increment.cpp and const2.cpp) 32

33 Constructors with Member Initializer
General form of ‘constructors’ Required for initializing ‘const’ data members (‘reference’ data members, NOT OFTEN used!) Member initializer list Each member initializer consists of the data member name followed by its initial value in parentheses is executed before the body of the constructor X::X(parameter-list) : initializer-list { … } 33

34 Examples OK OK 4433 NOT OK 34 class F { class F { public: public:
F() : i(j), m(3), k(m), j(4) { cout << i << j << k << m << endl; } private: const int& i; const int j; // ANSI C++ cannot have const int j = 4; int& k; int m; // ANSI C++ cannot have int m = 3; }; class F { public: F() : i(j), k(m), j(4) { m=3; cout << i << j << k << m << endl; } private: const int& i; const int j; int& k; int m; }; 4433 class F { public: F() : i(j), k(m) { m=3; j = 4; // compiler complains: assignment of read-only member `F::j' cout << i << j << k << m << endl; } private: const int& i; const int j; int& k; int m; }; NOT OK 34

35 Objects as class members

36 Objects as Members of Classes
A class can have objects of other classes as members Sometimes referred to as a ‘has-a’ relationship Example: Date.h, Date.cpp, Employee.h, Employee.cpp and composition.cpp class Employee { public: Employee(const char *const, const char *const, const Date&, const Date&); ~Employee(); void print() const; private: char firstName[25]; char lastName[25]; const Date birthDate; const Date hireDate; }; const T (const only modifies a type T), so it does not see the ‘*’ if you write const T*, therefore const char* p is a constant object. T *const is a constant pointer. Const T *const is both constant object and pointer const char *const: see ‘pointer’ slides. 36

37 Constructor Initializing member objects
Member initializers pass arguments from the object’s constructor to member-object constructors 1. initializers 2. member-object constructors 3. object constructors If a member initializer is not provided, the member object’s default constructor will be called implicitly Employee::Employee(const char *const first, const char *const last, const Date& dateOfBirth, const Date& dateOfHire) : birthDate(dateOfBirth), hireDate(dateOfHire) { ... } Member initializers pass arguments to Date’s implicit copy constructor (equivalent to const Date birthDate = dateOfBirth;) A compilation error occurs if a const member object is not initialized with a member initializer in the constructor 37

38 Example: Time Class Information hiding (Time.h and Time.cpp)
Two types of constructors class Time { public: Time(); Time(unsigned initHours, unsigned initMinutes, char initAMPM); void set(unsigned hours, unsigned minutes, char am_pm); void display(ostream& out) const; ... private: unsigned myHours, myMinutes; char myAMorPM; // 'A' or 'P' unsigned myMilTime; // military time equivalent }; 38

39 Default Constructor Time mealTime = Time();
Time::Time() : myHours(12), myMinutes(0), myAMorPM('A'), myMilTime(0) { // void } mealTime myHours 12 myMinutes myAMorPM A myMilTime Time mealTime = Time(); 39

40 Explicit-Value Constructor
Time::Time(unsigned initHours, unsigned initMinutes, char initAMPM) { set(initHours, initMinutes, initAMPM); //a member function } bedTime myHours 11 myMinutes 30 myAMorPM P myMilTime 2330 Time bedTime = Time(11,30,’P’); (a random value if myMilTime is not set in set()) 40 40 40

41 Constructors with Default Arguments
Constructors can specify default arguments Can initialize data members to a consistent state Even if no values are provided in a constructor call Constructor that defaults all its arguments is also a default constructor Can be invoked with no arguments Maximum of one default constructor per class 41

42 Possible to specify default values for constructor arguments
Time(unsigned initHours = 12, unsigned initMinutes = 0, char initAMPM = 'A'); Time t1, t2(5), t3(6,30), t4(8,15,'P'); t1 myHours 12 myMinutes myAMorPM A myMilTime t2 myHours 5 myMinutes myAMorPM A myMilTime 500 t3 myHours 6 myMinutes 30 myAMorPM A myMilTime 630 t4 myHours 8 myMinutes 15 myAMorPM P myMilTime 2015 42

43 Same as: Time t(bedTime); and calls ‘copy constructor’.
Copy Operations During initialization Time t = bedTime; During assignment t = midnight; t myHours 11 myMinutes 30 myAMorPM P myMilTime 2330 bedTime myHours 11 myMinutes 30 myAMorPM P myMilTime 2330 Same as: Time t(bedTime); and calls ‘copy constructor’. t myHours 12 myMinutes myAMorPM A myMilTime midnight myHours 12 myMinutes myAMorPM A myMilTime ‘assignment’, by default, memberwise copy of the left into the right object. 43

44 Other Class Operations
Accessors: "get" functions unsigned Time::getMinutes() const { return myMinutes; } unsigned Time::getHours() const { return myHours; } unsigned Time::getAMPM() const { return myAMorPM; unsigned Time::getMilTime() const { return myMilTime; 44

45 Mutators: "set" functions
void Time::set(unsigned hours, unsigned minutes, char am_pm) { // Check class invariant if (hours >= 1 && hours <= 12 && minutes >= 0 && minutes <= 59 && (am_pm == 'A' || am_pm == 'P')) { myHours = hours; myMinutes = minutes; myAMorPM = am_pm; myMilTime = toMilitary(hours, minutes, am_pm); } else cerr << "*** Can't set time with these values ***\n"; } 45


Download ppt "Classes: Part 2."

Similar presentations


Ads by Google