首页 > 试题广场 >

下面这段代码运行时会出现什么问题?

[单选题]
下面这段代码运行时会出现什么问题?
#include <stdio.h>
class A
{
public:
    void f()
    {
        printf("A\n");
    }
};

class B: public A
{
public:
    virtual void f()
    {
        printf("B\n");
    }
};

int main()
{
    A *a = new B;
    a->f();
    delete a;
    return 0;
}

	


  • 没有问题,输出B
  • 不符合预期的输出A
  • 程序不正确
  • 以上答案都不正确
推荐
答案:B

基类A 的f()没有声明为虚函数,所以没有B覆盖。
编辑于 2015-02-02 15:04:15 回复(1)

会内存泄露,释放了父类的内存,但是子类的内存没有释放

发表于 2017-11-01 18:09:14 回复(0)
说一下虚函数:
1.  被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。
2. C++中的虚函数的作用主要是实现了多态 的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。 所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。

发表于 2015-08-26 16:02:41 回复(4)
其实这个题程序崩溃的原因并不是内存泄露,内存泄露只是浪费点空间,不会对程序造成损坏。拿vc6.0来说,在堆中分配的内存是这个格式:FDFDFDFD 。。。。FDFDFDFD,FD中间是申请的内存空间。而回收的时候则是以这些FD来确定回收的内存。
这道题目父类没有虚函数,子类有虚函数。我们知道有虚函数的类,它会有一个虚函数指针vptr指向虚函数表,这个指针占4个字节。因为父类没有虚函数指针,所以在把子类指针赋给父类指针时,编译器会自动往后移4个字节。

那么在回收a指针指向的这个空间时,会因为找不到前面的FD而报错,最终这个开辟的空间也不会被回收。(子类和父类的都不会回收,因为它们的空间都是被同一组FD夹着,要回收得一起回收。父类析构完毕,并不代表它的内存能被回收。)
那么,怎么让程序不报错,并且内存回收正确?把a指针前移4个字节即可。



编辑于 2019-02-03 15:31:32 回复(5)
确实会输出A,但同时程序也会崩溃。
因为delete a这一句会出错,a实际还是一个B类型,但是析构函数没有声明为虚函数,导致调用了A的默认析构函数,内存溢出了。
发表于 2015-09-03 14:16:59 回复(9)
答案:
    B
解答:
1. B类继承A类,由于基类A中的f()没有被声明为virtual,因此不会被B中的f()覆盖,
   故B对对象中有的成员包括A->f(),B->f(),a->f()会调用A中的f(),打印出A。
2. A *a = new B; 会在堆上创建一个B类对象,父类指针a指向这个对象。由于基类A的
   析构函数没有声明为virtual,因此delete a时只会调用A类的默认析构函数,不会调用B类析构函数,
   使得堆中B类对象未被完全delete,造成内存泄漏。
   如果A类的析构函数为virtual,则会先调用B类的析构函数,然后再调A类析构函数。

发表于 2017-08-21 18:36:56 回复(1)
文字题,不符合预期的 输出A和不符合 预期的输出A,出题者我给你点赞
发表于 2017-11-19 22:15:42 回复(1)
注意一点,析构函数非虚,delete的时候不能调用class B的析构函数,导致内存泄漏。
发表于 2016-09-02 20:39:28 回复(0)
C++的动态多态性需要满足两个条件:
1.基类的函数为虚函数
2.设置基类指针指向继承类对象

看main函数里面,程序是想实现多态性的,满足了条件2。
但是由于调用的函数(析构函数)不是虚函数,也无法实现多态性;
无法实现多态性的情况下,调用函数的类型就是指针最初的类型!

看到有个评论的思路很好:
当基类的指针指向继承类时,指针是基类的,调用函数时就先寻找基类的对应函数;
假如该函数是虚函数,其实是在通知指针往继承类的方向寻找函数……
具体方向和基类指针指向的继承类有关。
编辑于 2018-11-09 09:36:38 回复(1)
A类的void f()声明为虚函数virtual,则不管B类的void f()是否声明为virtual,结果都是调用B的f()函数。父类指针指向子类对象,子类函数覆盖父类的虚函数
编辑于 2016-03-22 21:32:42 回复(0)
c++中的多态需要 父类指针指向子类对象,虚函数重写,特别重要的是在父类中的虚函数要用virtual。但是子类不是必须的。同时在本题中,因为只有子类声明了virtual,因此在delete a 时,只会调用父类的析构函数,因此造成b 内存泄露;菜鸟一个,欢迎交流与指正。
发表于 2020-03-28 21:10:01 回复(0)
为啥我刷c的题目 c++的题目也出来了?

发表于 2021-04-12 21:13:06 回复(0)
DKC头像 DKC
我就想输出A咋的,强行被人不符合预期了!!
发表于 2018-04-16 21:42:50 回复(0)
1. 基类的virtual会影响派生类,但是派生类声明的virtual不会影响基类
2. 此处基类的内存被释放了,但是派生类的内存未被释放
发表于 2018-03-19 10:15:16 回复(0)
为什么不选c
发表于 2015-12-20 16:48:36 回复(0)
首先,输出是A(已验证),因为a是指向A类型的指针,调用函数时,由于函数不是虚函数,所以他会调用A中的成员函数,而不会根据a实际指向的类型进行调用。
其次,B选项好坑,意思是:我预期的是B,但没符合我预期,输出的是A。(但我一直理解的是预期是A,输出的不符合预期。。。)
编辑于 2015-09-01 00:02:30 回复(1)
这道题理论上来说是不会发生内存泄漏的。
原因:堆区开辟的B对象后,使用A对象的指针接收,再delete A对象的指针。此时就已经将堆区的空间给释放了。
而为什么很多人说是内存泄漏呢?
是因为如果子类中有指针成员且指向堆区空间,那么这个时候,delete A对象的指针,是不会触发子类的析构函数调用,自然该成员指向的堆区也就不会被释放。
所以,是不会发生内存泄漏的。
发表于 2023-05-02 17:46:53 回复(0)
(转)说一下虚函数:
1.  被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。
2. C++中的虚函数的作用主要是实现了多态 的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。 所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。
编辑于 2018-07-31 10:55:35 回复(0)
复制到我编译器上报了好几个错
发表于 2018-01-17 22:07:05 回复(0)
这道题对我来说偏难
发表于 2017-10-23 21:30:34 回复(0)
问题不应该是 delete a吗? 没有析构掉b对象
发表于 2017-09-24 21:17:05 回复(0)