入门:c++系列问(五)关于析构函数的调用??

dongdandan 2003-05-12 11:37:36
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ii): i(ii) {cout<<"A constructor"<<endl;}
~A() {cout<<"~~~~A "<<endl;}
void f() const {cout<<"a:f"<<endl;}
};

class B {
int i;
public:
B(int ii):i(ii) {cout<<"b constructor"<<endl;}
~B() {cout<<"~~~~b "<<endl;}
void f() const {cout<<"b:f"<<endl;}
};

class C : public B,public A {

public:
C(int ii):A(ii),B(ii) {cout<<"c constructor"<<endl;}
~C() {cout<<"~~~~c "<<endl;} // Calls ~A() and ~B()
void f() const { // Redefinition
cout<<"~~~~fc "<<endl;
}
};
int f1(C c) { cout<<sizeof(c)<<endl; return 1;}
int f2(A c) {cout<<sizeof(c)<<endl; return 1;}
int f3(B c) {cout<<sizeof(c)<<endl; return 1;}
int main() {
C c(78);
f1(c); 输出为 :8。~~c ~~b ~~a
f2(c); 4 ~~a ~~a
f3(c); 4 ~~~b ~~b

我的问题是在f2和f3函数中为什么能有两次析构函数的调用?
我的理解:因为是值传递,而且发生了对象的切片,编译器应该调用默认的拷贝构造函数,完成按比特的拷贝,这样就调用了一次构造函数,离开函数时这个对象析构,此时调用析构函数,但是为什么会有两次调用呢????
...全文
49 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
pzytony 2003-05-28
  • 打赏
  • 举报
回复
up
up
up
up
loveghb 2003-05-28
  • 打赏
  • 举报
回复
顶到有人接上为止!!!
loveghb 2003-05-18
  • 打赏
  • 举报
回复
to:bruce007(有理想的狗)
数字不一样,这地球人都知道的!是32位和16位的区别吗。
我的意思是BC3.1中的结果可以想象,它只析构一次。
但是DEV-CPP的结果就怪了。

“其它的是BC3.1是比较老的编译器, 它的实现与新的标准不一样”
你的意思就是说BC3.1的是非标准的喽?
那么标准又是怎么说的呢?洗耳恭听了。
面向对象我真的是个白痴,希望大家讨论讨论。

bruce007 2003-05-15
  • 打赏
  • 举报
回复
这是我在BC3.1上做出的结果。
结果和老兄的都不一样,
数字不一样是因为在 BC3.1下指针大小是16位得
其它的是BC3.1是比较老的编译器, 它的实现与新的标准不一样
sr388 2003-05-15
  • 打赏
  • 举报
回复
这样做可以得到正确结果,即为基类A、B增加一个复制构造函数:

#include <iostream>

using namespace std;

class A{
int i;
public:
A(int ii): i(ii) {cout<<"A constructor"<<endl;}
~A() {cout<<"~~~~A "<<endl;}
A(const A& rhs) {cout << "A copy constructor" << endl; i = rhs.i ;}
void f() const {cout<<"a:f"<<endl;}
};

class B{
int i;
public:
B(int ii):i(ii) {cout<<"b constructor"<<endl;}
~B() {cout<<"~~~~b "<<endl;}
B(const B& rhs) {cout << "B copy constructor" << endl; i = rhs.i ;}
void f() const {cout<<"b:f"<<endl;}
};

class C : public B,public A {

public:
C(int ii):A(ii),B(ii) {cout<<"c constructor"<<endl;}
~C() {cout<<"~~~~c "<<endl;} // Calls ~A() and ~B()
void f() const { // Redefinition
cout<< "~~~~fc " << endl;
}
};

int f1(C c) { cout<<sizeof(c)<<endl; return 1;}
void f2(A c) {cout<<sizeof(c)<<endl; }
void f3(B c) {cout<<sizeof(c)<<endl; }

void main() {
C c(78);
f1(c);
f2(c);
f3(c);
}

运行结果:

b constructor
A constructor
c constructor
B copy constructor
A copy constructor
8
~~~~c
~~~~A
~~~~b
A copy constructor
4
~~~~A
B copy constructor
4
~~~~b
~~~~c
~~~~A
~~~~b

可见,对象正确的只析构了一次。但为什么增加了一个复制构造函数后对象的析构次数就正确了,我也不知道。请高手再分析。
cochen 2003-05-14
  • 打赏
  • 举报
回复
每组具有继承关系的虚函数都有一个虚指针管理,虚指针将根据调用该函数的对象在继承关系中的位置调用相应的虚函数,所以只要调用一次
aiyinsitan 2003-05-14
  • 打赏
  • 举报
回复
C是一个派生自A和B的类
构造函数的调用顺序是先基类后派生类, 而析构函数则反过来,
loveghb 2003-05-14
  • 打赏
  • 举报
回复
up once more!!
支持楼主

dongdandan 2003-05-14
  • 打赏
  • 举报
回复
up
zhangzhihl 2003-05-13
  • 打赏
  • 举报
回复
析构函数是构造函数的逆所以你的函数列表里面有两个析构函数,一个是继承的,还有一个是本身的。调用两次,因为第一次是子类,再一次就是父类。
headman 2003-05-13
  • 打赏
  • 举报
回复
TO: herohowk(),切割,大概就是切割了子类对象的一些属性,使它满足一个父类对象的空间。
TO: dongdandan(蛋蛋), 如果不用virtual声明析构函数,我认为发生调用两次析构的原因是因为其函数列表里面有两个析构函数,一个是继承的,还有一个是本身的。调用两次,因为第一次是子类,再一次就是父类。
dongdandan 2003-05-13
  • 打赏
  • 举报
回复
为什么改成虚析构函数就不是 出现两次? ~~a和两次~~b 谁给解释一下?
herohowk 2003-05-13
  • 打赏
  • 举报
回复
这个问题不清楚, 怎么切割有人讲讲吗?
loveghb 2003-05-13
  • 打赏
  • 举报
回复
b constructor
A constructor
c constructor
8
~~~~c
~~~~A
~~~~b
~~~~c
~~~~A
~~~~b
4
~~~~A
~~~~A
4
~~~~b
~~~~b
这是我在DEV-CPP上做出来的结果



b constructor
A constructor
c constructor
4
~~~~c
~~~~A
~~~~b
2
~~~~A
2
~~~~b
这是我在BC3.1上做出的结果。
结果和老兄的都不一样,真的是很奇怪的!
哈哈。
弟兄们!怎么解释?!
chenzhenbest 2003-05-12
  • 打赏
  • 举报
回复
gz
Peterwby 2003-05-12
  • 打赏
  • 举报
回复
up
herohowk 2003-05-12
  • 打赏
  • 举报
回复
在溪沟函数前使用virtual再看看拉, 原因自己想拉
liu_feng_fly 2003-05-12
  • 打赏
  • 举报
回复
这种情况下(一个类是为了派生而准备的),应该把析构函数设成virtual,你把class A和class B的析构函数都设成virtual 再看看。
dongdandan 2003-05-12
  • 打赏
  • 举报
回复
up

70,032

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧