c++博大精深,这是很多了解c++的人的感觉。越是深入,越是觉得她会给你很好的训练---让你成为真正的程序设计者。 我想从她的初始化工作着手,试图展现其一角,希望能有助于您提高学c++和程序设计的兴趣---然后,去发现、开拓吧,当你把你的智慧融入进去以后,一行行程序就不仅是程序了,因为它就有了生命。
关于c中的初始化相关部分,如指针,如全局变量与局部变量默认初始化的区别,如静态变量的默认初始化,就跳过。我们从类开始。 初始化是非常重要的工作,因为你的类(确切说是对象,程序)的执行过程就是一系列状态变换,而初态不正确,就不可能到达正确解了。 面向对象的c++中的初始化工作,是由构造函数来完成的,在其他场景可能称为构造器。这是大家都明白的。但是,展开来,或许您还未必清楚,如,如何设计好的默认初始化,哪些成员变量只有唯一的初始化形式,组合与继承的初始化,资源浅拷贝问题,无名对象的问题,特殊需要的初始化(实例对象须唯一化)等等。我将在vc7.0上调试程序,每次调试一个,谈一个问题,试图给您解释清楚。愿于您有所帮助。
这次就说说好的初始化过程与静态成员的初始化。 不管程序员如何,面向对象的c++中初始化工作是必须的!!你写了一个类,没有写构造函数,但是,系统会“暗暗的”给你一个系统默认的构造函数,在实例化对象的时候它就会工作---要知道,一旦你自己定义了构造函数,系统就不会再提供默认构造函数。 问题是,我们应该定义自己的构造函数。否则,系统多半是无法达到正确的初始状态的! 定义好的构造函数,应该是给出多版本的构造函数,作好安全检查工作。我们下面给出一个例子,由c++缔造者的例子改动迩来。 需要一个类,日期Date,它有成员变量day,month,year,执行一些相关操作。如何进行初始化工作?我们或许会见到下面的代码:
//... class Date { int d,m,y; public: Date(int dd=0,int mm=0,int yy=0) { d=dd; m=mm; y=yy; }
//... }; //...
这样的程序没有语法错误,可以工作,但不是正确工作。下面这个语句会怎么样呢? Date oneday(-2,10,2002); 作简单的检查,如下面的代码部分。也是于事无补的。如对下面的语句仍然是无能为力的:
Date oneday(29,2,1981);
//... class Date { int d,m,y; public: Date(int dd=0,int mm=0,int yy=0) { if(dd>=0&&yy>=0&&mm>=0&&m<=31){//??? d=dd; m=mm; y=yy; } //else ??? }
//... }; //...
更何况,我们可能会需要用string来初始化,用char *指针来初始化: string s="29/2/1981"; char *p="29/2/1981";
应该怎么办呢?我想你有必要好好审视你的初始化工作了!!!
我们来看一个设计实例: ///////////////////////////////////// //类Date(c++) // 用于初始化工作的例子,写于22/5/2003 ///////////////////////////////////////////////////////////////
//date.h #pragma once #include <iostream> using namespace std; enum Month{jan=1,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec}; class Date { //异常类(默认构造函数,因为我们只是抛出异常,甚至没有标志) class Bad_date{}; int d,y; Month m; //静态成员变量 static Date default_date; public: Date(int dd=0, Month mm=Month(0), int yy=0);
Date(string s) { /* 省去内容*/} Date(char *p) { /*省去内容*/} ~Date(void); static void set_default(int d, Month m, int y); int day(void) const; Month month(void) const; int year(void) const;
int leapyear(int y) { /*省去内容*/ return 0;} //... void Test(void); };
我们来看看实现部分:
//date.cpp #include "date.h" #using <mscorlib.dll>
//静态成员的初始化 Date Date::default_date(4,feb,1981);
Date::~Date(void) { } //详尽的初始化工作的例子 Date::Date(int dd, Month mm, int yy) { //(1) if(dd==0) dd=default_date.day();//test d=default_date.day() if(mm==0) mm=default_date.month();//test m=default_date.month() if(yy==0) yy=default_date.year();//test y=default_date.year() int max;
switch(mm) { case feb: max=28+leapyear(yy); break; case apr:case jun:case sep:case nov: max=30; break; case jan:case mar:case may:case jul:case aug:case oct:case dec: max=31; break; default: throw Bad_date(); } if(dd<1||max<dd||yy<0) throw Bad_date();
y=yy; m=mm; d=dd; }
void Date::set_default(int d, Month m, int y) { Date::default_date=Date(d,m,y); }
int Date::day(void) const { return d; }
Month Date::month(void) const { return m; }
int Date::year(void) const { return y; } //测试函数 void Date::Test(void) { std::cout<<"\n This is a test using class Date. \n" <<" The date is(day/month/year) :"<<d<<"/"<<m<<"/"<<y <<std::endl; std::cout<<"\n Thank you! \n\n"; }
这里,有几个需要注意的,就是: (1)构造函数的版本 Date(int dd=0, Month mm=Month(0), int yy=0); Date(string s) { /* 省去内容*/} Date(char *p) { /*省去内容*/} (2)静态成员提供默认的值 //静态成员变量 static Date default_date; //及接口 static void set_default(int d, Month m, int y); (3)异常管理 //异常类(默认构造函数,因为我们只是抛出异常,甚至没有标志) class Bad_date{}; (4)构造函数中较好的算法 这些都是我们初始化工作交好的保证! 用下面的文件程序测试,可得结果: //fmain.cpp #include "date.h"
void main() { Date oneDay; oneDay.Test(); } /*结果:
This is a test using class Date. The date is(day/month/year) :4/2/1981
Thank you!
Press any key to continue */
下面回到实现程序文件date.cpp,看(1)部分的代码。我后面注释了三行的代码。如果我用注释的代码换掉程序中的代码,您觉得会出现什么结果? 这是个问题,留到下次给出答案。一个中午就要完了,下次我将给您再详细的谈初始化工作中的其他问题。祝愿您快乐的学!

|