您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

C++子类对象―子类对象的构造和析构

时间:01-10来源:作者:点击数:

对象在使用之前,始终是要经历“构造”这个过程的。在第15章,我们了解到当一个对象的成员数据是另一个对象的时候,就先运行成员对象的构造函数,再运行父对象的构造函数。但是继承的出现,会引入子类的构造函数。这时候,这些构造函数的运行顺序又是怎样的呢?

子类对象的构造

讨论子类对象的构造,就是在讨论子类对象的生成方式。它是先生成父类对象的成员,再对其进行扩展呢,还是先生成子类对象的成员,然后再对其进行补充?我们还是修改一下程序17.3.2,用事实来解决这个问题:(程序17.4.1)

//node.h和linklist.h同程序17.3.2
//stack.h

#include "linklist.h"
class Stack:private Linklist//私有继承链表类
{
   public:
   bool push(int i,char c);
   bool pop(int &i,char &c);
   void show();
   Stack(int i,char c);
   Stack();
};
Stack::Stack(int i,char c):Linklist(i,c)//将子类构造函数的参数传递给父类的构造函数
{
   cout <<"Stack constructor with parameter is running..." <<endl;
}
Stack::Stack()//子类构造函数
{
   cout <<"Stack constructor is running..." <<endl;
}
bool Stack::push(int i,char c)
{
   while (pcurrent->next!=NULL)
   pcurrent=pcurrent->next;
   return Insert(i,c);
}
bool Stack::pop(int &i,char &c)
{
   while (pcurrent->next!=NULL)
   pcurrent=pcurrent->next;
   i=pcurrent->idata;
   c=pcurrent->cdata;
   return Delete();
}
void Stack::show()
{
   Show();
}

//main.cpp

#include <iostream>
#include "stack.h"
int main()
{
   Stack ss(1,'4');//调用带参数的构造函数
   cout <<"Stack ss constructed" <<endl;
   ss.show();
   Stack zz; //调用不带参数的构造函数
   cout <<"Stack zz constructed" <<endl;
   zz.show();
   return 0;
}

运行结果:
Node constructor is running...
Linklist constructor is running...
Stack constructor with parameter is running...
Stack ss constructed
1 4
Node constructor is running...
Linklist constructor is running...
Stack constructor is running...
Stack zz constructed
0 0
Linklist destructor is running...
Node destructor is running...
Linklist destructor is running...
Node destructor is running...

这个程序中有三个类,其中Stack类是Linklist类的子类,Node类的对象是Linklist类的成员数据。根据程序的运行结果,我们可以确定,父类的成员对象仍然是最先构造的,接着是运行父类的构造函数,最后运行子类的构造函数。也就是说子类对象是在父类对象的基础上扩展而成的。

另外,如果我们希望把子类的构造函数的参数传递给父类的构造函数时,可以在子类的构造函数定义中用以下格式调用父类的构造函数:
    子类名::构造函数名(参数表):父类名(参数表)

如程序17.4.1就是用上述方法实现子类和父类的构造函数参数传递。这样的方法不仅使子类对象的初始化变得简单,并且使子类和父类的构造函数分工明确,易于维护。

子类对象的析构

在第15章中介绍析构函数的时候,我们就说它的运行顺序往往是和构造函数的运行顺序相反的。那么使用了继承之后,是否依然是这样的规律呢?我们继续修改程序17.4.1,尝试验证我们的猜想。 

//node.h和linklist.h同程序17.3.2
//stack.h

#include "linklist.h"
class Stack:private Linklist
{
   public:
   bool push(int i,char c);
   bool pop(int &i,char &c);
   void show();
   Stack(int i,char c);
   Stack();
   ~Stack();//析构函数
};
Stack::Stack(int i,char c):Linklist(i,c)
{
   cout <<"Stack constructor with parameter is running..." <<endl;
}
Stack::Stack()
{
   cout <<"Stack constructor is running..." <<endl;
}
Stack::~Stack()
{
   cout <<"Stack destructor is running..." <<endl;
}
bool Stack::push(int i,char c)
{
   while (pcurrent->next!=NULL)
   pcurrent=pcurrent->next;
   return Insert(i,c);
}
bool Stack::pop(int &i,char &c)
{
   while (pcurrent->next!=NULL)
   pcurrent=pcurrent->next;
   i=pcurrent->idata;
   c=pcurrent->cdata;
   return Delete();
}
void Stack::show()
{
   Show();
}

//main.cpp

#include <iostream>
#include "stack.h"
int main()
{
   Stack zz;
   cout <<"Stack zz constructed" <<endl;
   zz.show();
   return 0;
}

运行结果:
Node constructor is running...
Linklist constructor is running...
Stack constructor is running...
Stack zz constructed
0 0
Stack destructor is running...
Linklist destructor is running...
Node destructor is running...

根据运行结果,我们可以确认:使用了继承之后,析构函数的运行顺序依然恰好与构造函数的运行顺序相反。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门