【5】类的深入剖析

const对象和const成员函数

最小特权原则
—private成员
—const对象和const成员
const Time noon(12 , 0 , 0);
常量对象不可被修改
常量对象的成员数据不可被修改

需要定义const成员函数“保证”不会修改成员数据的值

1 // Fig. 10.1: Time.h 
2 // Definition of class Time. 
3 // Member functions defined in Time.cpp. 
4 #ifndef TIME_H 
5 #define TIME_H 
6
7 class Time 
8 { 
9 public: 
10 Time( int = 0, int = 0, int = 0 ); // default constructor 
11
12 // set functions 
13 void setTime( int, int, int ); // set time 
14 void setHour( int ); // set hour 
15 void setMinute( int ); // set minute 
16 void setSecond( int ); // set second 
17
18 // get functions (normally declared const) 
19 int getHour() const; // return hour 
20 int getMinute() const; // return minute 
21 int getSecond() const; // return second
22
23 // print functions (normally declared const) 
24 void printUniversal() const; // print universal time 
25 void printStandard(); // print standard time (should be const) 
26 private: 
27 int hour; // 0 - 23 (24-hour clock format) 
28 int minute; // 0 - 59 
29 int second; // 0 - 59 
30 }; // end class Time 
31
32 #endif 
1 // Fig. 10.2: Time.cpp 
2 // Member-function definitions for class Time. 
3 #include <iostream> 
4 using std::cout; 
5
6 #include <iomanip> 
7 using std::setfill; 
8 using std::setw; 
9
10 #include "Time.h" // include definition of class Time 
11
12 // constructor function to initialize private data; 
13 // calls member function setTime to set variables; 
14 // default values are 0 (see class definition) 
15 Time::Time( int hour, int minute, int second ) 
16 { 
17 setTime( hour, minute, second ); 
18 } // end Time constructor 
19
20 // set hour, minute and second values 
21 void Time::setTime( int hour, int minute, int second ) 
22 { 
23 setHour( hour ); 
24 setMinute( minute ); 
25 setSecond( second ); 
26 } // end function setTime 
27
28 // set hour value 
29 void Time::setHour( int h ) 
30 { 
31 hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour 
32 } // end function setHour 
33
34 // set minute value 
35 void Time::setMinute( int m ) 
36 { 
37 minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute 
38 } // end function setMinute 
39
40 // set second value 
41 void Time::setSecond( int s ) 
42 { 
43 second = ( s >= 0 && s < 60 ) ? s : 0; // validate second 
44 } // end function setSecond 
45
46 // return hour value 
47 int Time::getHour() const // get functions should be const 
48 { 
49 return hour; 
50 } // end function getHour
51
52 // return minute value 
53 int Time::getMinute() const 
54 { 
55 return minute; 
56 } // end function getMinute 
57
58 // return second value 
59 int Time::getSecond() const 
60 { 
61 return second; 
62 } // end function getSecond 
63
64 // print Time in universal-time format (HH:MM:SS) 
65 void Time::printUniversal() const 
66 { 
67 cout << setfill( '0' ) << setw( 2 ) << hour << ":" 
68 << setw( 2 ) << minute << ":" << setw( 2 ) << second; 
69 } // end function printUniversal 
70
71 // print Time in standard-time format (HH:MM:SS AM or PM) 
72 void Time::printStandard() // note lack of const declaration 
73 { 
74 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) 
75 << ":" << setfill( '0' ) << setw( 2 ) << minute 
76 << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 
77 } // end function printStandard 

1 // Fig. 10.3: fig10_03.cpp 
2 // Attempting to access a const object with non-const member functions. 
3 #include "Time.h" // include Time class definition 
4
5 int main() 
6 { 
7 Time wakeUp( 6, 45, 0 ); // non-constant object 
8 const Time noon( 12, 0, 0 ); // constant object 
9
10 // OBJECT MEMBER FUNCTION 
11 wakeUp.setHour( 18 ); // non-const non-const 
12 
13 noon.setHour( 12 ); // const non-const 
14 
15 wakeUp.getHour(); // non-const const 
16 
17 noon.getMinute(); // const const 
18 noon.printUniversal(); // const const 
19 
20 noon.printStandard(); // const non-const 
21 return 0; 
22 } // end main 

const成员数

构造函数和析构函数不允许定义为const成员函数。
构造调用的set函数也不能定义成const成员函数。
const对象的“常量性质”在从构造函数完成对象的始化开始到对象的析构函数被调用结束

const成员

可以直接定义成员数据
—const成员函数保证该成员函数不能修改成员数据
—const成员数据保证任何成员函数不能修改该成员数据

1 // Fig. 10.4: Increment.h 
2 // Definition of class Increment. 
3 #ifndef INCREMENT_H 
4 #define INCREMENT_H 
5
6 class Increment 
7 { 
8 public: 
9 Increment( int c = 0, int i = 1 ); // default constructor 
10
11 // function addIncrement definition 
12 void addIncrement() 
13 { 
14 count += increment; 
15 } // end function addIncrement 
16
17 void print() const; // prints count and increment 
18 private: 
19 int count; 
20 const int increment; // const data member 
21 }; // end class Increment 
22
23 #endif

12行 :count©
用初始化器初始化const成员

1 // Fig. 10.5: Increment.cpp 
2 // Member-function definitions for class Increment demonstrate using a 
3 // member initializer to initialize a constant of a built-in data type. 
4 #include <iostream> 
5 using std::cout; 
6 using std::endl; 
7
8 #include "Increment.h" // include definition of class Increment 
9
10 // constructor 
11 Increment::Increment( int c, int i ) 
12 : count( c ), // initializer for non-const member 
13 increment( i ) // required initializer for const member 
14 { 
15 // empty body 
16 } // end constructor Increment 
17
18 // print count and increment values 
19 void Increment::print() const 
20 { 
21 cout << "count = " << count << ", increment = " << increment << endl; 
22 } // end function print
1 // Fig. 10.6: fig10_06.cpp 
2 // Program to test class Increment. 
3 #include <iostream> 
4 using std::cout; 
5
6 #include "Increment.h" // include definition of class Increment 
7
8 int main() 
9 { 
10 Increment value( 10, 5 ); 
11
12 cout << "Before incrementing: "; 
13 value.print(); 
14
15 for ( int j = 1; j <= 3; j++ ) 
16 { 
17 value.addIncrement(); 
18 cout << "After increment " << j << ": "; 
19 value.print(); 
20 } // end for 
21
22 return 0; 
23 } // end main 

Before incrementing: count = 10, increment = 5
After increment 1: count = 15, increment = 5
After increment 2: count = 20, increment = 5
After increment 3: count = 25, increment = 5

• const成员数据根据实际需要进行定义。
• 类中不需要修改成员数据的成员函数都需要定义成const成员函数。
const对象只能调用const成员函数

对象作成员——组成(包含)

在这里插入图片描述

1 // Fig. 10.10: Date.h 
2 // Date class definition; Member functions defined in Date.cpp 
3 #ifndef DATE_H 
4 #define DATE_H 
5
6 class Date 
7 { 
8 public: 
9 Date( int = 1, int = 1, int = 1900 ); // default constructor 
10 void print() const; // print date in month/day/year format 
11 ~Date(); // provided to confirm destruction order 
12 private: 
13 int month; // 1-12 (January-December) 
14 int day; // 1-31 based on month 
15 int year; // any year 
16
17 // utility function to check if day is proper for month and year 
18 int checkDay( int ) const; 
19 }; // end class Date 
20
21 #endif 

1 // Fig. 10.11: Date.cpp 
2 // Member-function definitions for class Date. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include "Date.h" // include Date class definition 
8
9 // constructor confirms proper value for month; calls 
10 // utility function checkDay to confirm proper value for day 
11 Date::Date( int mn, int dy, int yr ) 
12 { 
13 if ( mn > 0 && mn <= 12 ) // validate the month 
14 month = mn; 
15 else 
16 { 
17 month = 1; // invalid month set to 1 
18 cout << "Invalid month (" << mn << ") set to 1.\n"; 
19 } // end else 
20
21 year = yr; // could validate yr 
22 day = checkDay( dy ); // validate the day 
23
24 // output Date object to show when its constructor is called 
25 cout << "Date object constructor for date "; 
26 print(); 
27 cout << endl; 
28 } // end Date constructor
29
30 // print Date object in form month/day/year 
31 void Date::print() const 
32 { 
33 cout << month << '/' << day << '/' << year; 
34 } // end function print 
35
36 // output Date object to show when its destructor is called 
37 Date::~Date() 
38 { 
39 cout << "Date object destructor for date "; 
40 print(); 
41 cout << endl; 
42 } // end ~Date destructor
43
44 // utility function to confirm proper day value based on 
45 // month and year; handles leap years, too 
46 int Date::checkDay( int testDay ) const 
47 { 
48 static const int daysPerMonth[ 13 ] = 
49 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 
50
51 // determine whether testDay is valid for specified month 
52 if ( testDay > 0 && testDay <= daysPerMonth[ month ] ) 
53 return testDay; 
54
55 // February 29 check for leap year 
56 if ( month == 2 && testDay == 29 && ( year % 400 == 0 || 
57 ( year % 4 == 0 && year % 100 != 0 ) ) ) 
58 return testDay; 
59
60 cout << "Invalid day (" << testDay << ") set to 1.\n"; 
61 return 1; // leave object in consistent state if bad value 
62 } // end function checkDay
1 // Fig. 10.12: Employee.h 
2 // Employee class definition. 
3 // Member functions defined in Employee.cpp. 
4 #ifndef EMPLOYEE_H 
5 #define EMPLOYEE_H 
6
7 #include "Date.h" // include Date class definition 
8
9 class Employee 
10 { 
11 public: 
12 Employee( const char * const, const char * const, 
13 const Date &, const Date & ); 
14 void print() const; 
15 ~Employee(); // provided to confirm destruction order 
16 private: 
17 char firstName[ 25 ]; 
18 char lastName[ 25 ]; 
19 const Date birthDate; // composition: member object 
20 const Date hireDate; // composition: member object 
21 }; // end class Employee 
22
23 #endif 
1 // Fig. 10.13: Employee.cpp 
2 // Member-function definitions for class Employee. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include <cstring> // strlen and strncpy prototypes 
8 using std::strlen; 
9 using std::strncpy; 
10
11 #include "Employee.h" // Employee class definition 
12 #include "Date.h" // Date class definition 
13
14 // constructor uses member initializer list to pass initializer 
15 // values to constructors of member objects birthDate and hireDate 
16 // [Note: This invokes the so-called "default copy constructor" which the 
17 // C++ compiler provides implicitly.] 
18 Employee::Employee( const char * const first, const char * const last, 
19 const Date &dateOfBirth, const Date &dateOfHire ) 
20 : birthDate( dateOfBirth ), // initialize birthDate 
21 hireDate( dateOfHire ) // initialize hireDate 
22 { 
23 // copy first into firstName and be sure that it fits 
24 int length = strlen( first ); 
25 length = ( length < 25 ? length : 24 ); 
26 strncpy( firstName, first, length ); 
27 firstName[ length ] = '\0'; 
28
29 // copy last into lastName and be sure that it fits 
30 length = strlen( last ); 
31 length = ( length < 25 ? length : 24 ); 
32 strncpy( lastName, last, length ); 
33 lastName[ length ] = '\0'; 
34
35 // output Employee object to show when constructor is called 
36 cout << "Employee object constructor: " 
37 << firstName << ' ' << lastName << endl; 
38 } // end Employee constructor 
39
40 // print Employee object 
41 void Employee::print() const 
42 { 
43 cout << lastName << ", " << firstName << " Hired: "; 
44 hireDate.print(); 
45 cout << " Birthday: "; 
46 birthDate.print(); 
47 cout << endl; 
48 } // end function print 
49
50 // output Employee object to show when its destructor is called 
51 Employee::~Employee() 
52 { 
53 cout << "Employee object destructor: " 
54 << lastName << ", " << firstName << endl; 
55 } // end ~Employee destructor
1 // Fig. 10.14: fig10_14.cpp 
2 // Demonstrating composition--an object with member objects. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include "Employee.h" // Employee class definition 
8
9 int main() 
10 { 
11 Date birth( 7, 24, 1949 ); 
12 Date hire( 3, 12, 1988 ); 
13 Employee manager( "Bob", "Blue", birth, hire ); 
14
15 cout << endl; 
16 manager.print(); 
17
18 cout << "\nTest Date constructor with invalid values:\n"; 
19 Date lastDayOff( 14, 35, 1994 ); // invalid month and day 
20 cout << endl; 
21 return 0; 
22 } // end main 

Date object constructor for date 7/24/1949
Date object constructor for date 3/12/1988
Employee object constructor: Bob Blue

Blue, Bob Hired: 3/12/1988 Birthday: 7/24/1949

Test Date constructor with invalid values:
Invalid month (14) set to 1.
Invalid day (35) set to 1.
Date object constructor for date 1/1/1994

Date object destructor for date 1/1/1994
Employee object destructor: Blue, Bob
Date object destructor for date 3/12/1988
Date object destructor for date 7/24/1949
Date object destructor for date 3/12/1988
Date object destructor for date 7/24/1949

对象做成员

•成员对象的初始化只能通过初始化器实现。
•允许不对成员对象进行初始化,但成员对象对应的类必须定义缺省构造函数

作业

在这里插入图片描述
在这里插入图片描述

ctime 数据类型

time_t
时间类型,由time()返回,表示的时间是从一个时间点(1970年1月1日0时0分0秒)到此时的秒数
struct tm
结构体,表示为分解时间

ctime tm结构体

在这里插入图片描述

ctime 常用函数

• time函数
– 获取日历时间
– 函数原型:time_t time (time_t* timer);
– time(NULL); //返回当前系统时间
• gmtime函数
– 将日历时间转换为格林威治时间,返回结构体tm型指针
– 原型: struct tm * gmtime (const time_t * timer);
ctime函数
– 将日历时间转换为字符串
– 函数原型: char* ctime (const time_t * timer);
– 字符串格式:Www Mmm dd hh:mm:ss yyyy

int main()
{
time_t t;
t=time(NULL);
cout<<"当前日历时间:"<<t<<endl;
string ts=ctime(&t);
cout<<"时间字符串:"<<ts<<endl;
tm* pt=gmtime(&t);
int day=pt->tm_mday;
int month=pt->tm_mon+1;
int year=pt->tm_year+1900;
cout<<"tm截取年月日:"; 
cout<<year<<'-'<<month<<'-'<<day<<endl;
return 0;
}

friend函数

• 友元函数,是通过类的授权获得访问授权类私有成员的特权的非成员函数。
• 友元提高了程序的性能,但友元在一定程度上破坏了类的封装性

第十行(Count &,int)授权类对象充当友元函数的参数,友元函数对参数对象的私有成员拥有直接访问的特权

1 // Fig. 10.15: fig10_15.cpp 
2 // Friends can access private members of a class. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 // Count class definition 
8 class Count 
9 { 
10 friend void setX( Count &, int ); // friend declaration 
11 public: 
12 // constructor 
13 Count() 
14 : x( 0 ) // initialize x to 0 
15 { 
16 // empty body 
17 } // end constructor Count 
18
19 // output x 
20 void print() const 
21 { 
22 cout << x << endl; 
23 } // end function print 
24 private: 
25 int x; // data member 
26 }; // end class Count 
27
28 // function setX can modify private data of Count 
29 // because setX is declared as a friend of Count (line 10) 
30 void setX( Count &c, int val ) 
31 { 
32 c.x = val; // allowed because setX is a friend of Count 
33 } // end function setX 
34
35 int main() 
36 { 
37 Count counter; // create Count object 
38
39 cout << "counter.x after instantiation: "; 
40 counter.print(); 
41
42 setX( counter, 8 ); // set x using a friend function 
43 cout << "counter.x after call to setX friend function: "; 
44 counter.print(); 
45 return 0; 
46 } // end main 

counter.x after instantiation: 0
counter.x after call to setX friend function: 8

1 // Fig. 10.16: fig10_16.cpp 
2 // Non-friend/non-member functions cannot access private data of a class. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 // Count class definition (note that there is no friendship declaration) 
8 class Count 
9 { 
10 public: 
11 // constructor 
12 Count() 
13 : x( 0 ) // initialize x to 0 
14 { 
15 // empty body 
16 } // end constructor Count 
17
18 // output x 
19 void print() const 
20 { 
21 cout << x << endl; 
22 } // end function print 
23 private: 
24 int x; // data member 
25 }; // end class Count
26
27 // function cannotSetX tries to modify private data of Count, 
28 // but cannot because the function is not a friend of Count 
29 void cannotSetX( Count &c, int val ) 
30 { 
31 c.x = val; // ERROR: cannot access private member in Count 
32 } // end function cannotSetX 
33
34 int main() 
35 { 
36 Count counter; // create Count object 
37
38 cannotSetX( counter, 3 ); // cannotSetX is not a friend 
39 return 0; 
40 } // end main

this指针

在这里插入图片描述

1 // Fig. 10.17: fig10_17.cpp 
2 // Using the this pointer to refer to object members. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 class Test 
8 { 
9 public: 
10 Test( int = 0 ); // default constructor 
11 void print() const; 
12 private: 
13 int x; 
14 }; // end class Test 
15
16 // constructor 
17 Test::Test( int value ) 
18 : x( value ) // initialize x to value 
19 { 
20 // empty body 
21 } // end constructor Test 
22
23 // print x using implicit and explicit this pointers; 
24 // the parentheses around *this are required 
25 void Test::print() const 
26 { 
27 // implicitly use the this pointer to access the member x 
28 cout << " x = " << x; 
29
30 // explicitly use the this pointer and the arrow operator 
31 // to access the member x 
32 cout << "\n this->x = " << this->x; 
33
34 // explicitly use the dereferenced this pointer and 
35 // the dot operator to access the member x 
36 cout << "\n(*this).x = " << ( *this ).x << endl; 
37 } // end function print 
38
39 int main() 
40 { 
41 Test testObject( 12 ); // instantiate and initialize testObject 
42
43 testObject.print(); 
44 return 0; 
45 } // end main

x = 12
this->x = 12
(*this).x = 12

1 // Fig. 10.18: Time.h 
2 // Cascading member function calls. 
3
4 // Time class definition. 
5 // Member functions defined in Time.cpp. 
6 #ifndef TIME_H 
7 #define TIME_H 
8
9 class Time 
10 { 
11 public: 
12 Time( int = 0, int = 0, int = 0 ); // default constructor 
13
14 // set functions (the Time & return types enable cascading) 
15 Time &setTime( int, int, int ); // set hour, minute, second 
16 Time &setHour( int ); // set hour 
17 Time &setMinute( int ); // set minute 
18 Time &setSecond( int ); // set second
19
20 // get functions (normally declared const) 
21 int getHour() const; // return hour 
22 int getMinute() const; // return minute 
23 int getSecond() const; // return second 
24
25 // print functions (normally declared const) 
26 void printUniversal() const; // print universal time 
27 void printStandard() const; // print standard time 
28 private: 
29 int hour; // 0 - 23 (24-hour clock format) 
30 int minute; // 0 - 59 
31 int second; // 0 - 59 
32 }; // end class Time 
33
34 #endif 
1 // Fig. 10.19: Time.cpp 
2 // Member-function definitions for Time class. 
3 #include <iostream> 
4 using std::cout; 
5
6 #include <iomanip> 
7 using std::setfill; 
8 using std::setw; 
9
10 #include "Time.h" // Time class definition 
11
12 // constructor function to initialize private data; 
13 // calls member function setTime to set variables; 
14 // default values are 0 (see class definition) 
15 Time::Time( int hr, int min, int sec ) 
16 { 
17 setTime( hr, min, sec ); 
18 } // end Time constructor 
19
20 // set values of hour, minute, and second 
21 Time &Time::setTime( int h, int m, int s ) // note Time & return 
22 { 
23 setHour( h ); 
24 setMinute( m ); 
25 setSecond( s ); 
26 return *this; // enables cascading 
27 } // end function setTime 
28
29 // set hour value 
30 Time &Time::setHour( int h ) // note Time & return 
31 { 
32 hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour 
33 return *this; // enables cascading 
34 } // end function setHour 
35
36 // set minute value 
37 Time &Time::setMinute( int m ) // note Time & return 
38 { 
39 minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute 
40 return *this; // enables cascading 
41 } // end function setMinute 
42
43 // set second value 
44 Time &Time::setSecond( int s ) // note Time & return 
45 { 
46 second = ( s >= 0 && s < 60 ) ? s : 0; // validate second 
47 return *this; // enables cascading 
48 } // end function setSecond 
49
50 // get hour value 
51 int Time::getHour() const 
52 { 
53 return hour; 
54 } // end function getHour
55
56 // get minute value 
57 int Time::getMinute() const 
58 { 
59 return minute; 
60 } // end function getMinute 
61
62 // get second value 
63 int Time::getSecond() const 
64 { 
65 return second; 
66 } // end function getSecond 
67
68 // print Time in universal-time format (HH:MM:SS) 
69 void Time::printUniversal() const 
70 { 
71 cout << setfill( '0' ) << setw( 2 ) << hour << ":" 
72 << setw( 2 ) << minute << ":" << setw( 2 ) << second; 
73 } // end function printUniversal 
74
75 // print Time in standard-time format (HH:MM:SS AM or PM) 
76 void Time::printStandard() const 
77 { 
78 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) 
79 << ":" << setfill( '0' ) << setw( 2 ) << minute 
80 << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" ); 
81 } // end function printStandard
1 // Fig. 10.20: fig10_20.cpp 
2 // Cascading member function calls with the this pointer. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include "Time.h" // Time class definition 
8
9 int main() 
10 { 
11 Time t; // create Time object 
12
13 // cascaded function calls 
14 t.setHour( 18 ).setMinute( 30 ).setSecond( 22 ); 
15
16 // output time in universal and standard formats 
17 cout << "Universal time: "; 
18 t.printUniversal(); 
19
20 cout << "\nStandard time: "; 
21 t.printStandard(); 
22
23 cout << "\n\nNew standard time: "; 
24
25 // cascaded function calls 
26 t.setTime( 20, 20, 20 ).printStandard(); 
27 cout << endl; 
28 return 0; 
29 } // end main 

Universal time: 18:30:22
Standard time: 6:30:22 PM
New standard time: 8:20:20 PM

new和delete

• 变量、数组、对象的定义和声明一般要求在编译时即为对应的变量等分配内存空间。该
静态分配的空间在程序运行时不可改变大小,在生命期终止时由系统自动回收
• 使用不够灵活
• 与静态分配相对应的,可以用new运算在程序运行时根据需要动态的分配空间

• new <类型>
• new <类型> (初值)
• new <类型>[长度]
返回值为空间首地址

• double *dPtr=new double(3.14159);
• Time *timePtr=new Time(12,45,0);
• char *nameArry=new char[10];
• int *scoreArry=new int[students];
[students]动态空间的长度可以用变量表示

• 用new运算动态分配的空间不会被自动回收,一定要在动态空间生命期终止前用delete语句进行回收!
• 没有用delete回收的空间将会在内存中逻辑消失,直到计算机重新启动为止。这称为内存泄漏

静态成员

•用static定义的成员数据称为静态成员数据。
– 静态成员数据,是仅属于类的数据空间,不管有几个对象,静态成员数据只有一个拷贝,所有对象共享这个静态成员。用来存放同类对象的公共信息。
– 静态成员数据,只能在类外被定义并被初始化一次(int或者enum型可以类中声明处进行初始化)。其先于并独立于所有对象存在
•用static定义的成员函数成为静态成员函数。
– 静态成员函数,在没有类对象的情况下,只能通过public的静态成员函数访问private的静态成员数据。
– 静态成员函数是类的服务,不是对象的服务。
– 静态成员函数不接受this指针,因此不能访问非静态的成员数据

1 // Fig. 10.21: Employee.h 
2 // Employee class definition. 
3 #ifndef EMPLOYEE_H 
4 #define EMPLOYEE_H 
5
6 class Employee 
7 { 
8 public: 
9 Employee( const char * const, const char * const ); // constructor 
10 ~Employee(); // destructor 
11 const char *getFirstName() const; // return first name 
12 const char *getLastName() const; // return last name 
13
14 // static member function 
15 static int getCount(); // return number of objects instantiated 
16 private: 
17 char *firstName; 
18 char *lastName; 
19
20 // static data 
21 static int count; // number of objects instantiated 
22 }; // end class Employee 
23
24 #endif 
1 // Fig. 10.22: Employee.cpp 
2 // Member-function definitions for class Employee. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include <cstring> // strlen and strcpy prototypes 
8 using std::strlen; 
9 using std::strcpy; 
10
11 #include "Employee.h" // Employee class definition 
12
13 // define and initialize static data member at file scope 
14 int Employee::count = 0; 
15
16 // define static member function that returns number of 
17 // Employee objects instantiated (declared static in Employee.h) 
18 int Employee::getCount() 
19 { 
20 return count; 
21 } // end static function getCount
22
23 // constructor dynamically allocates space for first and last name and 
24 // uses strcpy to copy first and last names into the object 
25 Employee::Employee( const char * const first, const char * const last ) 
26 { 
27 firstName = new char[ strlen( first ) + 1 ]; 
28 strcpy( firstName, first ); 
29
30 lastName = new char[ strlen( last ) + 1 ]; 
31 strcpy( lastName, last ); 
32
33 count++; // increment static count of employees 
34
35 cout << "Employee constructor for " << firstName 
36 << ' ' << lastName << " called." << endl; 
37 } // end Employee constructor 
38
39 // destructor deallocates dynamically allocated memory 
40 Employee::~Employee() 
41 { 
42 cout << "~Employee() called for " << firstName 
43 << ' ' << lastName << endl; 
44
45 delete [] firstName; // release memory 
46 delete [] lastName; // release memory 
47
48 count--; // decrement static count of employees 
49 } // end ~Employee destructor
50
51 // return first name of employee 
52 const char *Employee::getFirstName() const 
53 { 
54 // const before return type prevents client from modifying 
55 // private data; client should copy returned string before 
56 // destructor deletes storage to prevent undefined pointer 
57 return firstName; 
58 } // end function getFirstName 
59
60 // return last name of employee 
61 const char *Employee::getLastName() const 
62 { 
63 // const before return type prevents client from modifying 
64 // private data; client should copy returned string before 
65 // destructor deletes storage to prevent undefined pointer 
66 return lastName; 
67 } // end function getLastName
1 // Fig. 10.23: fig10_23.cpp 
2 // Driver to test class Employee. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include "Employee.h" // Employee class definition 
8
9 int main() 
10 { 
11 // use class name and binary scope resolution operator to 
12 // access static number function getCount 
13 cout << "Number of employees before instantiation of any objects is " 
14 << Employee::getCount() << endl; // use class name 
15
16 // use new to dynamically create two new Employees 
17 // operator new also calls the object's constructor 
18 Employee *e1Ptr = new Employee( "Susan", "Baker" ); 
19 Employee *e2Ptr = new Employee( "Robert", "Jones" ); 
20
21 // call getCount on first Employee object 
22 cout << "Number of employees after objects are instantiated is " 
23 << e1Ptr->getCount(); 
24
25 cout << "\n\nEmployee 1: " 
26 << e1Ptr->getFirstName() << " " << e1Ptr->getLastName() 
27 << "\nEmployee 2: " 
28 << e2Ptr->getFirstName() << " " << e2Ptr->getLastName() << "\n\n";
29
30 delete e1Ptr; // deallocate memory 
31 e1Ptr = 0; // disconnect pointer from free-store space 
32 delete e2Ptr; // deallocate memory 
33 e2Ptr = 0; // disconnect pointer from free-store space 
34
35 // no objects exist, so call static member function getCount again 
36 // using the class name and the binary scope resolution operator 
37 cout << "Number of employees after objects are deleted is " 
38 << Employee::getCount() << endl; 
39 return 0; 
40 } // end main

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

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

• 有些编译系统规定,static成员函数只能通过类名前缀调用,不可以通过对象调用。
• static成员函数不能定义为const成员函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
深入剖析Tomcat(中文版+英文版)》.rar 《深入剖析Tomcat》深入剖析Tomcat 4和Tomcat 5中的每个组件(如果TOMCAT版本有点老,不过现在的Tomcat6和7同样可以借鉴参考),并揭示其内部工作原理。通过学习《深入剖析Tomcat》,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。作为一个开源和小型的轻量级应用服务器,Tomcat 易于使用,便于部署,但Tomcat本身是一个非常复杂的系统,包含了很多功能模块。这些功能模块构成了Tomcat的核心结构。《深入剖析Tomcat》从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。 目录 第1章 一个简单的web服务器 1.1 http 1.1.1 http请求 1.1.2 http响应 1.2 socket类 1.3 应用程序 1.3.1 httpserver类 1.3.2 request类 1.3.3 response类 1.3.4 运行应用程序 1.4 小结 第2章 一个简单的servlet容器 2.1 javax.servlet.servlet接口 2.2 应用程序 2.2.1 httpserver1类 2.2.2 request类 2.2.3 response类 2.2.4 staticresourceprocessor类 2.2.5 servletprocessor1类 2.2.6 运行应用程序 2.3 应用程序 2.4 小结 第3章 连接器 3.1 stringmanager类 3.2 应用程序 3.2.1 启动应用程序 3.2.2 httpconnector类 3.2.3 创建httprequest对象 3.2.4 创建httpresponse对象 3.2.5 静态资源处理器和servlet处理器 3.2.6 运行应用程序 3.3 小结 第4章 tomcat的默认连接器 4.1 http 1.1的新特性 4.1.1 持久连接 4.1.2 块编码 4.1.3 状态码100的使用 4.2 connector接口 4.3 httpconnector类 4.3.1 创建服务器套接字 4.3.2 维护httpprocessor实例 4.3.3 提供http请求服务 4.4 httpprocessor类 4.5 request对象 4.6 response对象 4.7 处理请求 4.7.1 解析连接 4.7.2 解析请求 4.7.3 解析请求头 4.8 简单的container应用程序 4.9 小结 第5章 servlet容器 5.1 container接口 5.2 管道任务 5.2.1 pipeline接口 5.2.2 valve接口 5.2.3 valvecontext接口 5.2.4 contained接口 5.3 wrapper接口 5.4 context接口 5.5 wrapper应用程序 5.5.1 ex05.pyrmont.core.simpleloader类 5.5.2 ex05.pyrmont.core.simplepipeline类 5.5.3 ex05.pyrmont.core.simplewrapper类 5.5.4 ex05.pyrmont.core.simplewrappervalve类 5.5.5 ex05.pyrmont.valves.clientiploggervalve类 5.5.6 ex05.pyrmont.valves.headerloggervalve类 5.5.7 ex05.pyrmont.startup.bootstrap1 5.5.8 运行应用程序 5.6 context应用程序 5.6.1 ex05.pyrmont.core.simplecontextvalve类 5.6.2 ex05.pyrmont.core.simplecontextmapper类 5.6.3 ex05.pyrmont.core.simplecontext类 5.6.4 ex05.pyrmont.startup.bootstrap 5.6.5 运行应用程序 5.7 小结 第6章 生命周期 第7章 日志记录器 第8章 载入器 第9章 session管理 第10章 安全性 第11章 standardwrapper 第12章 standardcontext类 第13章 host和engine 第14章 服务器组件和服务组件 第15章 digester库 第16章 关闭钩子 第17章 启动tomcat 第18章 部署器 第19章 manager应用程序的servlet类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空LA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值