slan的学习笔记

天马行空的想,脚踏实地的做!

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  27 随笔 :: 0 文章 :: 52 评论 :: 2 引用

2006年11月11日 #

今天突然来了兴致,想装个真正的LINUX系统,因为以前只是在虚拟机上运行,觉得那种速度实在是把活人憋死.
经过一番努力,最后终于装成功了.嘿嘿小高兴一下!

后来发现居然不能上网.请大家发表各自看法.
情况如下:
本人是校内局域网IP.
手动设置好了IP,DNS,并也保存了修改.
IP可以PING通,不过网关不行.

问题出在哪啊?请各位知情人士帮忙!
posted @ 2006-11-11 23:11 易来 阅读(848) 评论(2) 编辑

2006年11月8日 #

昏迷,
偶今天发现偶的博客看贴的人挺多.
可是就是没有一个回贴的.
这样可不厚道啊.
没有一个评论咋行?
希望大家多提意见.偶也好改进!
posted @ 2006-11-08 23:19 易来 阅读(152) 评论(5) 编辑

哈哈.终于在历时半天的时间中完成了博客大搬家.
此次搬家害我逃了半节上机课,错过下午午休时间.
不管怎样,搬家成功!
posted @ 2006-11-08 14:31 易来 阅读(44) 评论(0) 编辑

这学期暑假正式进入JAVA系列学习

先学JAVA语言基础,然后(选下列一类学习):

* GUI 类:JavaBean -> Swing -> JavaHelp -> Java2D -> Image IO -> JAI -> Java 3D ...
* Enterprise 类:JDBC -> JDO -> Servlet -> JSP -> EJB -> JMS -> JTA/JTS...
* J2ME 类


嘿嘿,这分明就是<爪蛙夜未眠>里面某人列的系列!

posted @ 2006-11-08 14:27 易来 阅读(353) 评论(0) 编辑

学习内容  课程名称 学时
1  计算机软件及网络基础  CNB    
2  结构化查询语言SQL,数据库体系结构及管理  SDM
3  ODBC、JDBC介绍和实例分析 OJDBC 
4  Java基本语法,JAVA语言概述,面向对象编程 JBO
5  程序逻辑及Java语言实现  LGJ
6  基于Java的程序设计方法  JDM
7  输入/输出处理、多线程与网络通信 CPD
8  基于Java开发项目的阶段实习 JPR
9  Java语法归纳讲解 JAVAC
10  HTML及JavaScript 介绍 HTJS
11  JSP编程语言的语法 JSP
12  Servlet编程语言语法 Servlet
13  JAVABEAN编程语言语法 JAVABEAN
14  MVC设计模式 MVC
 
15 基于JAVA、JSP、SERVLET 、JAVABEAN、JDBC的应用实习  PRJ 
16 软件编程规范,软件集成开发环境简介,面向对象的分析与设计方法 SJO

□ 第二阶段

   学习内容  课程名称 学时
1  Linux系统原理及常用命令 LIS   
2  Linux开发环境 LIP
3  关系数据库设计基本原理(ERD模型)  ERD
4  DB2的数据库对象、实例、表空间、用户管理、性能优化 DB2
5  ORACLE数据库安装、配置;结构化查询语言SQL ORACLE
6  PowerDesigner设计工具设计数据库系统 JSOLU
7  基于数据库软件开发项目的阶段实习 PRJ 

3.J2EE方向
   学习内容  课程名称  
1 EJB语法归纳讲解 EJB
2 Struts讲解 Str
3 XML语言的语法 XML
4 Web Services WS
5 Spring框架使用 Sp
6 工厂模式系统讲解 IOC
7 DAO模式
8 Hibernate语法与核心技术 HIB
9 IBM Websphere中间件的管理 WAS
10 Jbuilder开发工具 Jb
11 基于IBM Websphere的WSAD开发 WSAD
12 职业素质培养与沟通技巧 概述、商业礼仪、素质教育、沟通技巧,团队协作,思考方法、演讲与报告,就业指导。 CPD
   项目实战:科技部企业竞争情报检索系统(J2EE方向)     
13 软件工程: 需求分析、概要设计、详细设计、编码、测试、全面涉足的软件项目开发。代码审查、配置管理、项目管理、文档编写、质量保证体系等内容和相应工具的实际应用。 OOAD 
14 情报检索系统:
   该系统在IBM专家的指导下采用J2EE架构、面向对象设计方法,基于Linux操作系统、DB2数据库,用JSP、Servlet、JavaBean、XML技术,学员分组独立完成.ERD

posted @ 2006-11-08 14:25 易来 阅读(629) 评论(1) 编辑

可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时,
基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,
而不是基类中定义的成员函数(只要派生类改写了该成员函数)。
若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都
会调用基类中定义的那个函数。

程序1:

#i nclude <iostream>
using namecpace std;
class B0 //基类B0声明
{ public:
 void display(){cout<<"B0::display()"<<endl;} //公有成员函数
};
class B1: public B0 
{
 public:
 void display(){cout<<"B1::display()"<<endl;} 
};
class D1: public B1 
{
public:
 void display(){cout<<"D1::display()"<<endl;} 
};
void fun(B0 *ptr) 
{ ptr->display(); //"对象指针->成员名"  }
void main() //主函数
{ B0 b0; //声明B0类对象
 B1 b1; //声明B1类对象
 D1 d1; //声明D1类对象
 B0 *p; //声明B0类指针
 p=&b0; //B0类指针指向B0类对象
 fun(p);
 p=&b1; //B0类指针指向B1类对象
 fun(p);
 p=&d1; //B0类指针指向D1类对象
 fun(p);
}
运行结果:
B0::display()
B0::display()
B0::display()

程序2:
#i nclude <iostream>
using namespace std;
class B0 //基类B0声明
{public: //外部接口
 virtual void display() //虚成员函数
     {cout<<"B0::display()"<<endl;}
};
class B1: public B0 //公有派生
{ public:
       void display()  {  cout<<"B1::display()"<<endl;  }
};
class D1: public B1 //公有派生
{ public:
   void display() {  cout<<"D1::display()"<<endl;  }
};
void fun(B0 *ptr) //普通函数
{    ptr->display();    }
void main() //主函数
{ B0 b0,  *p; //声明基类对象和指针
 B1 b1; //声明派生类对象
 D1 d1; //声明派生类对象
 p=&b0;
 fun(p); //调用基类B0函数成员
 p=&b1;
 fun(p); //调用派生类B1函数成员
 p=&d1;
 fun(p); //调用派生类D1函数成员
}
运行结果:
B0::display()
B1::display()
D1::display()

虚函数是动态绑定的基础。
是非静态的成员函数。
在类的声明中,在函数原型之前写virtual。
virtual 只用来说明类声明中的原型,不能用在函数实现时。
具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。
本质:不是重载声明而是覆盖。
调用方式:通过基类指针或引用,执行时会 根据指针指向的对象的类,决定调用哪个函数。

posted @ 2006-11-08 14:25 易来 阅读(2565) 评论(1) 编辑

一个很简单的程序,请大家解释下结果的原因:

#i nclude<iostream>
using namespace std;
void main()
{
  int a=5;
  cout<<a<<a--<<a;
}

大家觉得结果是多少呢?为什么?

posted @ 2006-11-08 14:24 易来 阅读(237) 评论(12) 编辑

所有中国黑客和红客,我的同胞们:
  首先声明,我的计算机软件技术、黑客功底,可能不会比你们任何人差:

  我通读过 minix,tcp/ip,bsd,linux, pl1的源码,我拿过中国高级程序员证书,sun 的java证书,精通vc和unix,对缓冲区溢出,病毒,ddk等均有研究,所以我想我有资格对你们说几句话。

  (如果我提到的一些计算机名词和人名,你们居然不知道,那只能证明你们的无知,和不配称为黑客。)

  如果是真正的黑客,他会知道

  1.发明tcp/ip的是美国人 。

  2. linux的作者,linus大侠现在也在美国工作 。

  3. open source的开创人 stallman 也是美国人,他提倡软件不分国界的自由的精神 。

  4. free bsd 的作者是美国人,他的source 让真正的黑客受惠

  5.世界级软件科学大师 tanabaom,也是美国的客座教授,他的minix, ameba和教材教育了全世界几代黑客。

  提到这些,不是崇美,不是恐美,只想证明:

  1.很多大师级的美国黑客,他们的理念恰恰是自由、开放、无国界;他们的自由软件,开放源码,是与政治无关的,是超越国界的,给全世界人们带来福音。

  2.真正的黑客精神,如stallman所说,是要让人类超越计算机,成为计算机的主宰,从而成为自由的。

  所有的中国黑客和红客,我的同胞们:

  当你们正通过下载美国人写的黑客工具,来攻击美国网络,并且乐此不疲,以为这就是爱国行动的时候,是否想过:

  此时此刻,印度的软件人士,正在努力提高软件技术,他们的软件水平、软件产业已经超越了中国;难道我们不应该痛苦地承认这个现实,并且奋起直追吗?

  中国发明了火药,但是缺少研究精神,结果是被西方人研究改进了以后打中国,这样的教训还少吗?

  中国向来不缺爱国热情,但是我们缺少对科技的认真研究精神,知耻而后勇的追赶精神。难道我们不愿意承认这一点吗?

  从战术上来说,过早暴露自己的实力是不聪明的;冒昧地问一句,如果真的战争爆发了,您的黑客技术完全掌握好了吗,您已经为那一天的到来在进行技术储备吗?

  您有没有想向那些真正为中国科技做出杰出贡献的科学家如钱学森学习呢?

  所有的中国黑客和红客,我的同胞们:

  请把你们的聪明才智用到真正提高你们的水平,对国家的强大有帮助的地方吧:

  如果您愿意对国家有所贡献:

  1.中国的863计划中有一个重点研究项目: 并行计算,分布计算,向量计算。您愿意研究它吗?

  2. 作为现代通讯技术的一个根本数学基础,大合数的快速因子分解,还是一个难题。您愿意研究它吗?

  如果您想提高技术,对中国的软件技术有所贡献:

  1.研究 vc,java

  2.研究数据结构,去考高级程序员

  3. 研究操作系统,读minix source code

  4. 研究tcp/ip, rfc文档

  5. 通读linux, 才算达到黑客境界

  6. 学习 uml,rose,软件工程,达到系统分析员水平。

  如果您对提高中国的科技有兴趣,去研究生物基因,材料技术(纳米技术),计算机技术,航天技术……

  我的同胞们,我愿大声呐喊:

  一个真正的民族主义者,不是义和团,不是太平天国,不是闭关锁国,不是盲目仇外,不是不敢正视自己民族和文化的丑陋和缺点。

  真正的民族主义者是成熟的、清醒的、理智的、务实的民族主义。真正的民族主义者不是种族主义者,不是极端份子,不是战争狂人。

  真正的民族主义者以追求本民族——中华民族的利益最大化为目标、准则、信念。判断一个人是不是真正的民族主义者,判断标准很简单:看他是给本民族的整体利益带来好处,还是损害民族利益。真正的民族主义者最务实,因为他知道坚持原则,同时又懂得策略。让我们成为真正的顶尖黑客!让我们成为真正的民族主义者!

posted @ 2006-11-08 14:23 易来 阅读(238) 评论(2) 编辑

一.输出文件流成员函数

1.输出流的open函数
    要使用一个输出文件流(ofstream),必须在构造函数或open函数中把该流与一个特定的磁盘文件关联起来。在各种情况下,描述文件的参量是相同的。
当你打开一个与输出流关联.的文件时,通常指定一个open_mode标志,如下表所示。可以用按位OR(|)运算符组合这些标志,它们作为枚举器定义在ios类中。
表  输出文件流文件打开模式
标  志 功         能
ios::app 打开一个输出文件用于在文件尾添加数据
ios::ate 打开一个现存文件(用于输入或输出)并查找到结尾
ios::in 打开一个输入文件对于一个ofstream文件,使用ios::in作为一个openmode可避免删除一个现存文件中现有的内容 ios::out    打开二个文件,用于输出。对于所有ofstream对象,此模式是隐含指定的 ios::nocreate    如果一个文件存在则打开它,否则该操作失败 i。
s::noreplace 如果一个文件不存在则作为新文件打开它,如果文件已存在,则该操作失败
ios::trunc 打开一个文件,如果它已经存在则删除其中原有的内容如果指定了ios::out,但没有指定iOs::ate、iOs::app和ios::in,则隐含为此模式
ios::binary 以二进制模式打开一个文件(缺省是文本模式)
有三个公共输出流涉及模式选项:
•建立一个文件,如果该文件己存在,则删除旧的版本:
ostream ofile("FILENAME");//缺省模式是ios::out
ofstream ofile("FILENAME",ios::out);//与上一句等效
•添加记录到一个现存文件中,如果文件不存在便建立一个新文件:
ofstream ofile(“FiILENAME”,ios::app);
•使用同一个流先后打开不同的文件(在同一时刻只有一个是打开的):
ofstream ofile();
ofile.open("FTILE1",ios::in)    //打开文件FILEl
…//    向文件FILEl
输出 ofile.close();    //关闭FILEl
ofile.open("FILE2",ios::in);    //打开文件FILE2
…//    向文件FILE2输出
ofile.close();    //关闭FILE2
//当对象ofile离开它的作用域时便消亡
2.put函数  
put函数把一个字符写到输出流中,下面两个语句缺省是相同的,但第二个受该流的格式化参量的影响:
cout.put(‘A’);    //精确地输出一个字符
cout<<"A";    //输出一个字符,但此前设置的宽度和填充方式在此起作用
3.write函数
write函数把一个内存中的一块内容写到一个输出文件流中,长度参数指出写的字节数。下面的例子建立一个输出文件流并将Date结构的二进制值写入文件:
例   向文件输出
#i nclude<fstream.h>
struct Date    
{
    int mo,da,yr;
};    
void main()
{    
    Date dt={6,10,92};
    ofstream tfile("date.dat",ios::binary);
    tfile.write((char*)&dt,sizeof dt);
}
write函数当遇到空字符时并不停止,因此能够写入完整的类结构,该函数带两个参量,一个char指针(指向内存数据的起始地址)和一个所写的字节数。注意在该结构对象的地址之前需要char*做强制类型转换。
4.seekp和tellp函数    
一个输出文件流保存一个内部指针指出下一次写数据的位置。seekp成员函数设置这个指针,因此可以以随机方式向磁盘文件输出。tellp成员函数返回该文件位置指针值。
5.输出流的close函数  
close成员函数关闭与一个输出文件流关联的磁盘文件。文件使用完毕后必须将其关闭以完成所有磁盘输出。虽然ofstream析构函数(destructor)会自动完成关闭,但如果需要在同一流对象上打开另外的文件,就需要使用close函数。    
如果构造函数或open成员函数打开了该文件,输出流析构函数自动关闭一个流的文件。
6.错误处理函数
错误处理成员函数的作用是在写到一个流时进行错误处理。各函数及其功能如下表所示。    
错误处理成员函数及其功能
函  数 功能及返回值
bad 如果出现一个不可恢复的错误,则返回一个非0值
fail 如果出现一个不可恢复的错误或一个预期的条件,例如一个转换错误或文件未找到,用返回一个非0值。在用零参量调用clear之后可能经常恢复处理
good 如果没有错误条件(不可恢复的或其他)和没有设置文件结尾标志,则返回一个非0值
eof 遇到文件结尾条件,则返回一个非0值
clear 设置内部错误状态,如果用缺省参量调用,则清除所有错误位
rdstate 返回当前错误状态
                          
! 运算符经过了重载,它与fail函数执行相同的功能,因此表达式if(! cout)等价于 if (cout.fail())。
void*()运算符也是经过重载的,与!运算符相反,因此表达式if(cout)等价于if(! cout.fail())。
void*()运算符不等价于good,因为它不检测文件结尾。
(四)二进制输出文件
最初设计流的目的是用于文本,因此缺省的输出模式是文本方式。在以文本模式输出时,若遇到换行符(十进制10),便自动被扩充为回车换行符(十进制13)。这种自动扩充有时可能出问题,请看下列程序:
#i nclude<fstream.h>
int iarray[2]={99,10};
void main()
{
    ofstream os("test.dat");
    os.write((char  *)iarray,sizeof(iarray));
}  
  
当执行程序,向文件中输出时,10会被自动转换成13,然而这里的转换显然不是我们需要的。要想解决这一问题,就要采用二进制模式输出。使用二进制模式输出时,其中所写的字符是不转换的。使用二进制模式输出到文件有下列几种方法,
(1)以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改变模式,例如:
    ofstream ofs("test.dat");
    ofs.setmode(filebuf::binary);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据
(2)使用ofstream构造函数中的模式参量指定二进制输出模式,例如:
#i nclude<fstream.h>
#i nclude<fcntl.h>
#i nclude<io.h>
int iarray[2]={99,10};
void main()
{
ofstream ofs("test.dat",ios::binary);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据
}
(3)使用二进制操作符代替setmode成员函数:
ofs<<binary;
若使用text操作符便把流切换到文本转换模式。
(4)使用open函数带一个二进制模式标志打开文件,例如:
filedesc fd=open("test.dat",OBINARY|OCREAT|OWRONLY);
ofstream ofs(fd);
ofs.write((char*)iarray,4);    //向二进制文件中写入4字节数据

二.输入流成员函数

输人流成员函数用于从磁盘文件中输入,这些成员函数包括:
    •open函数    
    •get函数    
    •getline函数
    •read函数    
    •seekg和tellg函数
    •close函数    
1.输入流的open函数
如果要使用一个输入文件流(ifstream),必须在构造函数中或者使用open函数把该流与一个特定磁盘文件关联起来。无论哪种方式,参量是相同的。
当打开与一个输入流关联的文件时,通常要指定一个模式标志。模式标志如下表所示,该标志可以用按位OR(|)运算符进行组合。
表  输入文件流文件打开模式
ios::in    打开文件用于输入(缺省)
ios::nocreate   如果文件不存在,该函数失败
ios::binary 以二进制模式(缺省模式是文本模式)打开文件
注意:如果需要测试文件是否存在,必须在打开文件时指定ios::nocreate模式,然后使用fail成员函数确定:
    istream ifile("FILENAME",ios::nocreate);
    if (ifile.fail())
    //The file does not exist...
2.get函数    
非格式化get函数的功能与提取运算符(>>)很相像,主要的不同点是get函数在读人数据时包括空白字符,而提取运算符在缺省情况下拒绝接受空白字符。
例  get函数应用举例
#i nclude<iostream.h>
void main()    
{
    char ch;
    while((ch=cin.get())!=EOF)
  cout.put(ch);
}
运行时如果输入:
abc  xyz  123
则输出:
abc  xyz  123
3.getline函数
getline成员函数的功能是允许从输人流中读取多个字符,并且允许指定输入终止字符(缺省值是换行字符),在读取完成后,从读取的内容中删除该终止字符。
例   为输入流指定一个终止字符
本程序连续读人一串字符,直到遇到字符‘t’时停止,字符个数最多不超过99个。
  #i nclude<iostream.h>
void main()
{    
    char line[100];
    cout<<"Type a 1ine terminated by "t""<<endl;
    cin.getline(1ine,100,"t");
    cout<<line;
}
4.read函数
read成员函数从一个文件读字节到一个指定的存储器区域,由长度参数确定要读的字节数。如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时读结束。
例   从一个payroll文件读一个二进制记录到一个结构中
    #i nclude<io.h>
void main()    
{
    struct
    {
  double salary;
  char name[23];
}employee;
ifstream is("payroll",ios::binary|ios::nocreate);
    if (is)
    {
    is.read((char*)&employee,sizeof(employee));
    cout<<employee.name<<" "<<employee.salary<<endl;
    }
    else
    {
    cout<<"ERROR:Cannot openfile"payroll"."<<endl;
    }    
}    
这里假设数据记录是通过指定的结构严格格式化的,并且设有终止的回车或换行字符。
5.seekg和tellg函数    
在输入文件流中,保留着一个指向文件中下一个将读数据的位置的内部指针,可以用 seekg函数来设置这个指针。    
    例   用seekg函数设置位置指针
  #i nclude<fstream.h>
void main()
{    
char ch;
ifstream tfile("payroll",ios::binary | ios::nocreate);
if(tfile)    
{
  tfile.seekg(8);    
  while(tfile.good())    
  {
   //遇到文件结束或读取操作失败时结束读操作
   tfile.get(ch);
   if (!ch)break;    //如果没有读到则退出循环
   cout<<ch;
  }
    }
    else
    {
  cout<<"ERROR;Cannot open file "payroll"."<<endl;
}    
}
  
使用seekg可以实现面向记录的数据管理系统,用固定长度的记录尺寸乘以记录号便得到相对于文件末尾的字节位置,然后使用get读这个记录。
tellg成员函数返回当前文件读指针的位置,这个值是streampos类型,该typedef结构定义在iostream.h中。
例   读一个文件并显示出其中空格的位置
#i nclude<fstream.h>
void main()
{    
    char ch;
    ifstream tfile("payroll",ios::binary | ios::nocreate);
    if (tfile)    
    {    
  while(tfile.good())    
  {
   streampos here=tfile.tellg();
   tfile.get(ch);
   if(ch==" ")
    cout<<"\nPosition"<<here<<"is a space";
  }
    }    
    else
    {    
   cout<<"ERROR:Cannot open file "payroll"."<<endl;
    }
}    
6.输入流的close函数
close成员函数关闭与一个输入文件流关联的磁盘文件。
虽然ifstream类的析构函数可以自动关闭文件,但是如果需要使用同一流对象打开另一文件,则首先要用close函数关闭当前文件。
四、输入/输出流
一个iostream对象可以是数据的源或目的。两个重要的I/O流类都是从iostream派生的,它们是fstream和strstream。这些类继承了前面描述的stream和ostream类的功能。
fstream类支持磁盘文件的输入和输出。如果你需要在同一个程序中从一个特定磁盘文件读和写到该磁盘文件,可以构造一个fstream对象。一个istream对象是有两个逻辑子流的单个流,两个子流一个用于输入,另一个用于输出。详细说明请读者参考联机帮助或运行库参考手册

posted @ 2006-11-08 14:22 易来 阅读(3286) 评论(1) 编辑

1。调用默认构造函数

例如,下面的程序定义了学号类和学生类,学生类中包含有学号类:

    //***********************
    //**   ch12_10.cpp  **
    //***********************

    #i nclude <iostream.h>
    #i nclude <string.h>

    int nextStudentID=0;
    class StudentID{
     public:
      StudentID()
      {
       value=++nextStudentID;
       cout <<"Assigning student id " <<value <<endl;
      }
      ~StudentID()
      {
       --nextStudentID;
       cout <<"Destructing id " <<value <<endl;
      }
     protected:
      int value;
    };

    class Student{
     public:
      Student(char* pName="noName")
      {
       cout <<"Constructing student " <<pName <<endl;

       strncpy(name,pName,sizeof(name));
       name[sizeof(name)-1]='\0';
      }
     protected:
      char name[20];
      StudentID id;
    };

    void main()
    {
      Student s("Randy");
    }

  运行结果为:
    Assigning student id 1
    Constructing student Randy
    Destructing id 1

  当学生类对象被构造时,一个学号赋予了该学生对象。
  学号类StudentlD含有保护数据成员value,按规定不能被另一个类Student的类对象访问,即使Student类包含StudentlD类。
  Student类包含一个成员id,id属于StudentID类,Student构造函数不能访问id对象中的保护数据成员。所以,在Student类对象构造时,须调用StudentID类的构造函数来初始化id。这就是类与类之间“互不干涉内政”的严酷关系。
  “Students("Randy");”语句执行步骤如下:
  (1)分配s对象空间,调用Student构造函数。
  (2)建立s对象空间中的结构,第一为name[20],第二为id,因它属于StudentID类,所以调用StudentID的构造函数,这时,id的保护数据value得到了赋值,全局变量nextStudentID得到了赋值,并且输出第一行信息。之后,返回到Student构造函数。
  (3)执行Student构造函数体。输出第二行信息,数据成员name得到了赋值。之后返回到主函数main()。
  如果Student类未定义构造函数,C++提供的默认构造函数将自动地为各个数据成员(如果是类对象的话)调用构造函数。程序结束时也与此相同。类的析构函数将自动地为各个具有析构函数的数据成员调用析构函数。
  我们看到,上面的例子中,Student构造函数调用了StudentID的默认构造函数。但如果想调用的构造函数不是默认构造函数,那又如何呢?
2。有参数的情况:

程序基本不变:

Student(char* pName="noName",int ssID=0)
      {
       cout <<"Constructing student " <<pName <<endl;

       strncpy(name,pName,sizeof(name));
       name[sizeof(name)-1]='\0';
       StudentID id(ssID); //希望将学号传给学号类对象(有点修改)
      }
StudentID的构造函数改为从参数中接受一个学号值。在Student构造函数内部,增加了一条语句“StudentID id(ssID);”,企图将ssID参数值传给数据成员id但实际上,在Student构造函数中构造了一个名为id的StudentID局部对象。由于是局部对象,所以,当Student构造函数返回时,便析构了这个对象。

那么,能否像下面这样在Student类中直接给id对象初始化呢?
    class Student
    {
     public:
      Student(char* pName="noName",int ssID);
     protected:
      char name[20];
      StudentID id(9818);
        //error:类定义是不分配空间和初始化的。
    };

  “StudentID id(9818);”是创建对象语句,而不是类定义中允许的声明数据成员形式
  “StudentlD id=9818;”或者“StudentID id(ssID);” 也都是不允许的。前者就是“StudentID id(9818);”后者ssID成了参数,类定义是不会调用构造函数的。因为类是一个抽象的概念,并不是一个实体,并不含有属性值,而只有对象才占有一定的空间,含有明确的属性值。我们只能按照格式“类型标识符;”去声明类的数据成员。

3。总结:

主程序不变:修改如下

Student(char* pName="noName",int ssID=0):id(ssID)
      {
       cout <<"Constructing student " <<pName <<endl;

       strncpy(name,pName,sizeof(name));
       name[sizeof(name)-1]='\0';
      }

冒号表示后面要对类的数据成员的构造函数进行调用。SSID可以是Student构造函数的形参,id(ssID)表示调用以ssID为实参的Student构造函数。

上例中,Student构造函数头冒号后面如果是id()的形式,表示调用Student的默认构造函数,并且可以省略。

posted @ 2006-11-08 14:21 易来 阅读(428) 评论(0) 编辑