首页 > 试题广场 >

有如下程序段,则程序输出?

[单选题]
有如下程序段:
#include <iostream>
using namespace std;

class A {
  public:
    ~A() { cout << "~A()"; }
};
class B {
  public:
    virtual ~B() { cout << "~B()"; }
};
class C : public A, public B {
  public:
    ~C() { cout << "~C()"; }
};
int main() {
    C *c = new C;
    B *b1 = dynamic_cast<B *>(c);
    A *a2 = dynamic_cast<A *>(b1);
    delete a2;
}
则程序输出:
  • ~C()~B()~A()
  • ~C()~A()~B()
  • A)B)都有可能
  • 以上都不对
推荐
答案:选D
答案解析:创建一个类对象c,然后动态类型转换,让一个B *b1指针指向c,再一次动态类型转换,让一个基类A *a2指针指向b1,当delete a2时,调用析构函数,但是基类A的析构函数不是虚函数,所以只调用A的析构函数,结果应该是:~A()
编辑于 2015-02-04 18:15:37 回复(3)
 B * b1 = dynamic_cast<B *>(c);  //这一句能成功
 A * a2 = dynamic_cast<A *>(b1); //转换不成功吧
发表于 2017-05-14 11:37:41 回复(0)
程序崩溃了

发表于 2016-07-20 16:19:24 回复(0)
main()函数中,第一句只用了new,调用了构造函数,没用delete,不会调用析构函数,内存泄露。第二句、第三句只是定义了指向不同对象的指针,不会产生对象,所以构造函数、析构函数都没调用,最后一句delete调用析构函数,因为基类A的析构函数不是虚函数,所以只调用A的析构函数,输出:~A(),如果A的析构函数加上virtual, 输出:~C()~B()~A(),与直接delete c输出一样。 析构函数声明为虚函数,这样析构时,先调用派生类的析构函数,再调用基类的析构函数,防止内存泄露。
编辑于 2015-10-17 15:54:56 回复(6)
一眼看出,new与delete肯定配套使用的,一个分配动态内存,一个释放动态内存,既然new C,那么delete C!

发表于 2015-08-22 00:07:28 回复(2)
动态的多态通过虚函数实现,基类指针指向派生类的对象,若指针调用的函数派生类中存在,且在基类中声明为虚函数,则调用的函数是派生类中的函数。
析构函数总是要声明为虚函数,这样析构时,先调用派生类的析构函数,再调用基类的析构函数,防止内存造成泄露
A类的析构函数未声明为虚函数,所以A类的指针,只可以调用A类的析构函数
发表于 2015-08-31 23:28:58 回复(0)
A * a2 = dynamic_cast<A *>(b1);
转型失败
发表于 2015-08-17 22:23:39 回复(3)
main()函数中,第一句只用了new,调用了构造函数,没用delete,不会调用析构函数,内存泄露。第二句、第三句只是定义了指向不同对象的指针,不会产生对象,所以构造函数、析构函数都没调用,最后一句delete调用析构函数,因为 style="color: rgb(102,102,102);">基类A的析构函数不是虚函数,所以只调用A的析构函数,输出:~A(),如果A的析构函数加上virtual, 输出:~C()~B()~A(),与直接delete c输出一样。 析构函数声明为虚函数,这样析构时,先调用派生类的析构函数,再调用基类的析构函数,防止内存泄露。
发表于 2023-10-04 21:45:23 回复(0)
最后打印 ~A()

发表于 2017-06-11 09:50:47 回复(0)
创建一个类对象c,然后动态类型转换,让一个B *b1指针指向c,再一次动态类型转换,让一个基类A *a2指针指向b1,当delete a2时,调用析构函数,但是基类A的析构函数不是虚函数,所以只调用A的析构函数,结果应该是:~A()
发表于 2022-10-28 20:45:57 回复(0)
main()函数中,第一句只用了new,调用了构造函数,没用delete,不会调用析构函数,内存泄露。第二句、第三句只是定义了指向不同对象的指针,不会产生对象,所以构造函数、析构函数都没调用,最后一句delete调用析构函数,因为 style="color: rgb(102,102,102);">基类A的析构函数不是虚函数,所以只调用A的析构函数,输出:~A(),如果A的析构函数加上virtual, 输出:~C()~B()~A(),与直接delete c输出一样。 析构函数声明为虚函数,这样析构时,先调用派生类的析构函数,再调用基类的析构函数,防止内存泄露。
发表于 2022-09-23 19:51:36 回复(0)
为什么第二次类型转换能够成功?

发表于 2022-03-10 10:14:03 回复(0)
基类转派生类可以,派生类转基类容易失败,
发表于 2022-01-05 13:17:32 回复(0)
通过基类的指针删除派生类对象时,通常情况下只调用基类的析构函数.m但是,删除一个派生类的对象时,应该先调用派生类的析构函数,然后调用基类的析构函数。派生类的析构函数可以virtual不进行声明.  通过基类的指针删除派生类对象时,首先调用派生类的析构函数,然后调用基类的析构函数...
一般来说,一个类如果定义了虚函数,则应该将析构函数也定义成虚函数。或者,一个类打算作为基类使用,也应该将析构函数定义成虚函数。选D

发表于 2020-07-29 17:17:12 回复(0)
delete会自动调用析构函数,所以只有delete a2才调用析构函数,因为A的析构函数不是虚函数,所以没有多态,则调用本身的虚函数。

发表于 2019-03-06 19:44:23 回复(0)
A的析构函数不是虚函数,应输出~A(),若加上virtual则输出~C()~B()~A(),故选D。
编辑于 2018-11-29 18:41:47 回复(0)
class A 是基类,  class B和class C是派生类。基类不是虚函数,直接调用。如果class A是虚函数,在析构函数的作用下,根据数据保护,程序会先走派生类,再走基类。
发表于 2018-10-05 10:00:30 回复(0)
删除指针时,如果该指针是指向派生类的基类指针,需要将基类析构函数定义为虚函数,才能保证调用的是指针动态绑定的对象,否则就会调用基类的析构函数。若将~A()定义为虚函数,则调用的是c的析构函数,调用派生类的析构函数前,会先调用基类的析构函数
发表于 2018-08-15 19:18:18 回复(0)
delete a2是未定义行为
所以正确答案是ABCD都有可能
发表于 2018-04-21 22:14:30 回复(0)
为什呢
发表于 2018-03-29 20:35:20 回复(0)
dynamic_cast将子类指针转化为父类指针的向上转型总是安全的,不需要rtti,不需要多态类型,编译时期就能判断是否合法; 向下转型要求父类有虚方法,即多态,或者其本质为带转换的指针对象(new 出来的),因为编译器都是通过虚表来找到rtti信息的。 本题中b1 a2本质都是c类,故转化可以成功
编辑于 2017-09-12 09:12:50 回复(0)