computer 版 (精华区)

发信人: remember (明天会更好), 信区: program
标  题: 关于 C++自测题(1)
发信站: 听涛站 (2001年09月30日12:12:22 星期天), 站内信件

(1)About Constructors and Destructors
我们先来看看运行结果吧:
(为了便于讨论,我加上了行号)
--- begin ---
01 Stack::Stack()

02 Stack::Stack(int)

03 Stack::Stack()
04 MyStack::MyStack(int)

05 Stack::Stack()
06 MyStack::MyStack(int)

07 Stack::Stack()
08 MyStack::MyStack(int)

09 Stack::Stack()
10 MyStack::MyStack(int)

11 Stack::~Stack()

12 MyStack::~MyStack()
13 Stack::~Stack()

14 MyStack::~MyStack()
15 Stack::~Stack()

16 MyStack::~MyStack()
17 Stack::~Stack()

18 MyStack::~MyStack()
19 Stack::~Stack()
20 Stack::~Stack()
--- end ---
相信运行结果还是不难想出的。这里我们看几个问题:
1.显然,子类的Constructor在执行前会调用父类的Constructor,在
  不指定Constructor类型是,用的是默认的Constructor,即不带参
  数;//参见3、5、7、9行
  那么,如果我们需要指定调用父类的某种Constructor呢?
  MyStack(int maxsize=1024):Stack(maxsize) { ... }
  这里,就指定使用父类的带一个int参数的构造函数;自然,就不再
  调用Stack()了。
2.调用析构函数的时候,先调用自身的析构函数,然后再调父类的析构
  函数。这表明我们释放动态分配的空间时需要小心,否则很可能会把
  同一空间释放两次而造成程序中止。——尽管编译器会检查指针是否
  为空,但对程序显式指明的释放操作还是照执行不误。考察下面一段
  程序:(基于源程序做适当修改)
  class Stack {
  public:
     Stack(){ p=new int(10); cout...}
     virtual ~Stack() { delete p; cout...}
     int *p;
     ...
  }
  class MyStack : public Stack {
  public:
     ...
     ~Stack() { delete p; cout...}
  }
  那么,p就被释放了两次,编译通过,但运行出错。
  释放指针时适当的考虑加入如 if (!p)一类判断还是一个不错的习惯
  ——尽管这种判断通常被认为多此一举;
  当然,以下情况是不会发生运行错误的:
  我们在MyStack的析构函数中不释放指针,而在Stack的析构函数中在
  delete p; 前加入 p=0;
  ——尽管在析构函数中调用delete p;后的(p==0)
  其中区别,大概要追究编译模式了。或说,编译模式中,Stack的析构
  函数的delete p;一行,在编译时,编译器检查Stack内对p的操作,确
  人p现在非空,然后执行delete操作,但可惜的是我们在MyStack中已
  经把p所占用的heap空间释放了...
  当然,这个解释不一定正确,是我个人看法而已,手上没有<<C++ Primer>>
  没法仔细研究这里的差异。
3.我们开始定义了stack_a和stack_d,可以看到,在释放对象的时候,
  是先释放stack_d,然后再到stack_a,看来释放对象的顺序和定义
  时的顺序刚好颠倒,是LIFO型。
4.如果把MyStack(int maxsize=1024)改为MyStack(int maxsize),
  编译是否通过?如果不通过,为什么?
  显然,这是因为去除默认值后,没有了Mystack的无参构造函数,在执
  行new MyStack()时出错。那么,为什么我们去除MyStack的这种构造
  函数(也就是MyStack没有声明任何构造函数)时,当然,new MyStack(256)
  之类还是报错,但把这类调用也去掉后,new MyStack()就不出错呢?
  看来当你没有声明任何构造函数的情况下,编译器自动构造一个默认的
  构造函数,如同如下代码:
  MyStack(){} //编译器自动生成的默认构造函数
  自然,还是先调用父类的默认构造函数了。

ok,罗罗嗦嗦说了这么多,也不再多说了,如果大家有什么疑问,大家一起
讨论讨论吧~~~

--
    洛阳亲友如相问  一片冰心在玉壶
※ 来源:·听涛站 tingtao.dhs.org·[FROM: 匿名天使的家] 
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.261毫秒