继承和析构函数 - 理论问题 - C++
class A
{
public:
virtual void f(){ printf("A.f "); }
~A(){ f(); }
};
class B : public A
{
A a;
public:
void f(){ printf("B.f "); }
B(){ throw -1; }
~B(){ f(); }
};
int main()
{
try{ B b; }
catch(...){ printf("Exc");}
}
这就是我的看法。在 try 块内,构造 B b;
时不会打印任何内容。区块结束。我认为编译器首先破坏 A a;
成员。因此将打印 Af()
。这是否意味着B类
实例的销毁已经完成?之后,编译器会简单地调用 ~A()
(破坏基类)吗?
我想我应该先得到 Af()
,然后是 Bf()
(破坏类 B 实例),然后再次得到 Af()
(基类的析构函数)。编译这个让我思考了一些。 当然,Exc 会在最后打印。 我已经浏览了几个主题,但没有找到任何东西。
编辑:Dev-C++ (GCC 3.4.2) 的输出是
AF AF 执行
class A
{
public:
virtual void f(){ printf("A.f "); }
~A(){ f(); }
};
class B : public A
{
A a;
public:
void f(){ printf("B.f "); }
B(){ throw -1; }
~B(){ f(); }
};
int main()
{
try{ B b; }
catch(...){ printf("Exc");}
}
So here's how I see it. Inside the try block, nothing is being printed while constructing B b;
. The block ends. I think compiler is destructing the A a;
member first. So A.f()
would be printed. Does that mean the destruction of class B
instance is finished? After that, would compiler simply call ~A()
(destructing base class)?
I thought I should've got A.f()
, then B.f()
(destructing class B instance) and after that A.f()
again (destructor of base class). Compiling this made me think a little.
Exc is being printed at the end of course.
I've gone through several topic and haven't found anything.
EDIT: Output from Dev-C++ (GCC 3.4.2) is
A.f A.f Exc
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这里确实有两个
A
对象。B
继承自A
,因此A
的基类对象先于 B 实例化。A
类型的成员字段作为B
的一部分时,就会创建另一个A
实例。当您创建
B b
时,您将创建基类A
以及实例A a
。但是,您随后在 B 的构造函数中抛出异常,因此此时所有完全构造的对象都将被破坏。
~A()
在实例A a
上调用。~A()
在基类A
上调用。这可以解释为什么你会得到
Af Af Exc
。B
的析构函数不会被调用,因为B
没有完全构造,因为它的构造函数没有成功完成。You really have two
A
objects here.B
inherits fromA
, so a base class object ofA
is instantiated first before B is.A
instance is created as you have a member field of typeA
as part ofB
.When you create
B b
, you create the base classA
, and also the instanceA a
.However, you then throw the exception in
B
's constructor, so then all fully-constructed objects at that point are destructed, that is.~A()
is called on the instanceA a
.~A()
is called on the base classA
.That would explain why you get
A.f A.f Exc
.B
's destructor would not be called becauseB
wasn't fully constructed as its constructor did not finish successfully.您没有向我们展示您得到的输出,只是一堵胡言乱语的文字,所以很难知道您在问什么。
但是,根据记录,代码的输出是:
为什么?
b
失败。b
的B
析构函数,但其成员的析构函数为1。A
类型的成员,其析构函数调用函数f()
。A
基础的b
;因此,b
的A
析构函数也被调用,像以前一样调用A::f()
。Exc
当然是由周围的异常处理程序输出的。这是你想知道的吗?
1:
You haven't shown us the output you get, just a wall of ranty text, so it's hard to know what you're asking.
However, for the record, the output of your code is:
Why?
b
fails.b
'sB
destructor is not invoked, but destructors for its members are1.A
, whose destructor calls the functionf()
.A
base ofb
; so,b
'sA
destructor is also invoked, callingA::f()
as before.Exc
is of course output by the surrounding exception handler.Is this what you wanted to know?
1:
顺序应该是:
Af, Af, Exc
当调用 B 的构造函数时,在进入之前,由于继承,首先调用 A 的构造函数。接下来,在进入B的构造函数之前(即
{
之前),默认构造a
。仅当 B 达到匹配的
}
时,B 的构造才算完成。但在此之前你有一个 throw 语句。因此,部分构造的 B 必须被销毁,它有一个对象a
和继承的子对象 A。因此,这两个对象都被销毁,因此 Af 和 Af接下来,您将到达 throw 块,其中 'Exc'被打印
The order should be:
A.f, A.f, Exc
When B's constructor is invoked, before entering, first A's constructor is invoked due to inheritance. Next, before entering B's constructor (i.e. before
{
),a
is default constructed.B's construction would be complete only if it reaches matching
}
. But before that you have a throw statement. So the partially constructed B has to be destroyed, which has one objecta
and the the inherited subobject A. So both these are destroyed, hence A.f and A.fNext, you reach the throw block where 'Exc' is printed
A 的析构函数被调用了两次,就是这样。
输出:
Destructor of A is called twice, that's it.
Output:
您不能从构造函数或析构函数调用虚函数。它们不会作为虚拟函数工作,而是被称为非虚拟函数。
您可以在常见问题解答此处阅读相关内容 以及有关构造函数的相关主题 此处。
You can't call virtual functions from constructor or destructor. They won't work as virtual but will be called as non-virtual functions.
You can read about it in FAQ here and in related theme about constructors here.