首页 > 试题广场 >

不能说明为虚函数的是( )。

[单选题]
C++类当中,不能声明为虚函数的是( )。
  • 析构函数
  • 构造函数
  • 类的成员函数
  • 以上都不对

构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。

不建议在构造函数和析构函数里面调用虚函数。

构造函数不能声明为虚函数的原因是:
1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。

2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。

虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。

析构函数设为虚函数的作用:
解释: 在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。
Note:
1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。
2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。
3. 有虚函数的类,几乎可以确定要有个虚析构函数。
4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。
5. 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。
6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现
7.
析构函数中 也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。
编辑于 2017-06-05 17:42:59 回复(1)
1:只有类的成员函数才能说明为虚函数; 
2:静态成员函数不能是虚函数; 
3:内联函数不能为虚函数; 
4:构造函数不能是虚函数; 
5:析构函数可以是虚函数,而且通常声明为虚函数。
发表于 2017-05-18 16:37:08 回复(1)
析构函数可以被声明为虚函数,而构造函数不能,是因为虚函数的调用是基于对象的实际类型来确定的,而构造函数在对象创建的过程中被调用,此时对象的实际类型还不确定。

当使用基类指针或引用指向派生类对象,并通过该指针或引用调用析构函数时,如果析构函数不是虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数。这样就会导致派生类对象中的资源无法正确释放,可能会造成内存泄漏或其他问题。

通过将析构函数声明为虚函数,可以确保在通过基类指针或引用调用析构函数时,会根据对象的实际类型来调用正确的析构函数,从而正确释放对象的资源。这是因为虚函数表(vtable)的机制会在运行时动态地确定调用的是哪个类的析构函数。

而构造函数在对象创建的过程中被调用,此时对象的实际类型还不确定,无法使用虚函数表来动态地确定调用哪个类的构造函数。因此,构造函数不能被声明为虚函数。


发表于 2023-06-29 14:20:31 回复(0)
在析构函数里调用虚函数和析构函数为虚函数,是不一样的
发表于 2018-09-30 09:45:10 回复(0)