⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 07章 类与数据抽象(二).txt

📁 C++大学教程txt版中文版 C++大学教程txt版中文版
💻 TXT
📖 第 1 页 / 共 5 页
字号:
  
图7.3显示的是用赋值语句而不用成员初始化值初始化increment时C++编译器产生的编译错误。

1 // Fig. 7.3: fig07_03.cpp
2 // Atempting to initialize a costant of
3 // a built-in data type with an assignment.
4 #include <iostream.h>
6 class Increment {
7 public:
8   Increment( int c = 0, int i = 1 );
9   void addIncrement() { count += increment; }
10  void print() const;
11 private:
12   int Count;
13   const int increment;
14 };
15
16 // Constructor for class Increment
17 Increment::Increment( int c, int i)
18 {  // Constant member ~ncrement'  is not initialized
19   count = c;
20   increment = i;  // ERROR: Cannot modify a const object
21 }
22
23 // Print the data
24 void Increment::print() const
25 {
26   cout << "count =" << count
27        << ", increment =" << increment << endl;
28 }
29
30 int main{)
31 {
32   Increment value( 10, 5 );
33
34   cout << "Before incrementing: ";
35   value.print();
36
37   for ( int j = 0; j < 3: j++ } {
38     value.addIncrement();
39     cout << "After increment "<< j << ": ";
40     value.print{);
41   }
42
43   return 0;
44 }

输出结果:
Compiling...
FigT_3.cpp
Fig7_3.cpp(18) : error: 'increment':
     must be initialized in constructor base/member
     initializer list
Fig7 3.cpp(20) : error: 1-value specifies const object

                      图7 3  用赋值语句初始化内部数据类型的常量时产生的编译错误

    常见编程错误7.5
    不为const数据成员提供成员初始化值是个语法错误。
    
    软件工程视点7 5
    常量类成员(const对象和const“变量”)要用成员初始化值的语法初始化,而不能用赋值语句。
    注意第24行将print函数声明为const,但不会有const类型的Inerement对象。

    软件工程视点7. 6
    如果成员函数不修改对象,最好将其声明const。如果不需要生成该类的const类型对象,则这样做是没有必要的。但将这种成员函数声明为const有一个好处,如果不小心修改了这个成员函数中的对象,则编泽器全产生一个语法错误的消息。
测试与调试提示 7.2
    C++之类的语言是不断演变的,新的关键字不断出现。不要用“object'’之类的标识符。尽管”object”
  目前还不是C++中的关键字,但将来很可能变成关键字,新的编译器可能不能接受现有代码。
    C++提供了新的关键字mutable,能够对程序中const对象进行处理。第21章将介绍关键字
mutable。

7.3  复合:把对象作为类成员
    AlarmClock类的对象需要知道何时响钤,因此可以将一个Time对象作为类成员,这种功能称为复合(composition)。类可以将其他类对象作为自己的成员。
  
    软件工程视点7.7
    复合是软件复用的一种形式,就是一个类将其他类对象作为自己的成员。
  
    生成对象时,自动调用其构造函数,因此要指定参数如何传递给成员对象的构造函数。成员对象按声明的顺序(而不是在构造函数的成虽初始化值列表中列出的顺序)并在建立所包含的类对象(也称为宿主对象,host object)之前建立。
    图7.4用Employee类和Date类演示一个类作为其他类对象的成员。Employee类包含private数据成员firstName、lastName、birthDate和hireDate。成员birthDate和hireDate是Date类的const类型的对象,该Data类包含private数据成员month、day和year。程序实例化一个Employee对象,并初始化和显示其数据成员。注意Employee构造函数定义中函数首部的语法:
Employee::Employee( char *fname, char *lname,
                    int bmonth, int bday, int byear,
                    int hmonth, int hday, int hyear )
     :birthDate (bmonth, bday, byear),
     hireDate (hmonth, hday, hyear )
该构造函数有八个参数(fname、lname、bmonth、bday、byear、hmonth、hday和hyear)。首部中的冒号(:)将成员初始化值与参数表分开。成员初始化值指定Employee的参数传递给成员对象的构造函数。参数bmonth、bday和byear传递给birthDate构造函数。参数hmonth、hday和hyear传递给hireDate构造函数。多个成员的初始化值用逗号分开。
1 // Fig. 7.4: datel.h
2 // Declaration of the Date class.
3 // Member functions defined in datel.cpp
4 #ifndef DATE1_H
5 #define DATE1_H
6
7 class Date {
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
14   int day;
15   int year;    // any year
16
17   // utility function to test proper day for month and year
18   int checkDay( int );
19 };
2O
21 #endif
22 // Fig. 7.4: date.cpp
23 // Member function definitions for Date class.
24 #include <iostream.h>
25 #include "date1.h"
26
27 // Constructor: Confirm proper value for month;
28 // call utility function checkDay to confirm proper
29 // value for day.
30 Date::Date( int mn, int dy, int yr )
31 {
32   if ( mn > 0 && mn <= 12 )      // validate the month
33     month = mn;
34   else {
35     month = 1;
36     cout << "Month "<< mn <<" invalid. Set to month 1.\n";
37   }
38
39   year = yr;                  // should validate yr
40   day = checkDay( dy );         // validate the day
41
42   cout << "Date object constructor for date ";
43   print();       // interesting: a print with no arguments
44   cout << endl;
45 }
46
47 // Print Date object in form month/day/year
48 void Date::print() const
49   { cout << month << '/' << day << '/' << year; }
5O
51 // Destructor: provided to confirm destruction order
52 Date::~Date()
53 {
54   cout << "Date object destructor for date ";
55   print();
56   cout << endl;
57 }
58
59 // Utility function to confirm proper day value
60 // based on month and year.
61 // Is the year 2000 a leap year?
62 int Date::checkDay( int testDay )
63 {
64   static const int daysPerMonth[ 13 ] =
65     {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
66
67   if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
68     return testDay;
69 
70     if ( month == 2 &&
71        testDay == 29 &&
72        ( year % 400 == 0 ||                  // year 2000?
73        ( year % 4 == 0 && year % 100 != 0 ) ) ) // year 2000?
74        return testDay;
75
76     cout << "Day" << testDay << "invalid. Set to day 1.\n";
77
78    return 1;  // leave object in consistent state if bad value
79 }
80 // Fig.7.4:emply1.h
81 // Declaration of the Employee class.
82 // Member functions defined in emplyl.cpp
83 #ifndef EMPLY1_H
84 #define EMPLY1_H
85
86 #include "date1.h"
87
88 class Employee {
89 public:
90   Employee( char *, char *, int, int, int, int, int, int );
91   void print() const;
92   ~Employee();  // provided to confirm destruction order
93 private:
94   char firstName[ 25 ];
95   char lastName[ 25 ];
96   const Date birthDate;
97   const Date hireDate;
98 };
99
100 #endif
101 // Fig. 7.4: emplyl.cpp
105 #include "emplyl.h"
107
108 Employee::Employee( char *fname, char *lname,
109                 int bmonth, int bday, int byear,
110                 int hmonth, int hday, int hyear )
111   : birthDate( bmonth, bday, byear ),
112         hireDate( hmonth, hday, hyear )
113 {
114      // copy fname into firstName and be sure that it fits
115      int length = strlen( fname );
116      length = ( length < 25 ? length : 24 );
117      strncpy( firstName, fname, length );
118      firstName[ length ] = '\0';
119
120      // copy lname into lastName and be sure that it fits
121      length = strlen( lname );
122      length = ( length < 25 ? length : 24 );
123      strncpy( lastName, lname, length );
124      lastName[ length ] = '\0';
125
126   cout << "Employee object constructor:"
127        << firstName << ' ' << lastName << endl;
128 }
129
130 void Employee::print() const
131 {
132   cout << lastName << ", "<< firstName << "\nHired: ";
133   hireDate.print();
134   cout <<" Birth date: ";
135   birthDate.print();
136   cout << endl;
137 }
138
139 // Destructor: provided to confirm destruction order
140 Employee::~Employee()
141 {
142   cout << "Employee object destructor:"
143        << lastName << ", "<< firstName << endl;
144 }
145 // Fig. 7.4: figO7_O4.cpp
147 #include <iostream.h>
148 #include "emply1.h"
149
150 int main()
151 {
152   Employee e( "Bob", "Jones", 7, 24, 1949, 3, 12, 1988 );
153
154   cout << '\n';
155   e.print();
156
157   cout << "\nTest Date constructor with invalid values:\n";
158   Date d( 14, 35, 1994 );  // invalid Date values

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -