C++中为什么构造函数不能是虚函数,析构函数是虚函数

一, 什么是虚函数?

简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。

所谓虚函数就是多态情况下只执行一个,而从继承的概念来讲,总是要先构造父类对象,然后才能是子类对象,如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的调用构造,还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错.

析构函数在某些情况下必须为虚函数(比如你想让你类能够被继承,那么这个类的析构函数最好是虚的,继承一个析构函数不是虚的类是有风险的),值得补充的是,当基类的函数是虚函数,子类的重载的函数也是虚的,即使不加virtual关键字也是虚的。

如果子类覆盖的父类的虚函数则父类的指针或引用实际指向子类的对象或指向自己的对象那通过该指针或引用调用虚函数时,则将调用子类的(虚)函数

如果不是虚函数,则将调用父类的函数
class A{

public:

virtual void print(){ cout<<”This is A”<<endl;} //现在成了虚函数了

};

class B:public A{

public:

void print(){ cout<<”This is B”<<endl;} //这里需要在前面加上关键字virtual吗?

};

毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了。

现在重新运行main2的代码,这样输出的结果就是This is A和This is B了。



int main(){ //main2

A a;

B b;

A* p1=&a;

A* p2=&b;

p1->print();

p2->print();

}

析构函数应定义为虚函数,否则容易发生内存泄露

1. 为什么构造函数不能为虚函数?

虚函数的调用需要虚函数表指针,而该指针存放在对象的内容空间中;若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表地址用来调用虚函数——构造函数了。

2. 为什么析构函数可以为虚函数,如果不设为虚函数可能会存在什么问题?

首先析构函数可以为虚函数,而且当要使用基类指针或引用调用子类时,最好将基类的析构函数声明为虚函数,否则可以存在内存泄露的问题。

举例说明:

子类B继承自基类A;A *p = new B; delete p;

1) 此时,如果类A的析构函数不是虚函数,那么delete p;将会仅仅调用A的析构函数,只释放了B对象中的A部分,而派生出的新的部分未释放掉。

2) 如果类A的析构函数是虚函数,delete p; 将会先调用B的析构函数,再调用A的析构函数,释放B对象的所有空间。

补充: B *p = new B; delete p;时也是先调用B的析构函数,再调用A的析构函数。

[from]

http://zhidao.baidu.com/question/32424351.html

http://www.cnblogs.com/zhice163/archive/2012/07/10/2584835.html

时间: 2024-11-05 09:17:16

C++中为什么构造函数不能是虚函数,析构函数是虚函数的相关文章

c++中虚函数和纯虚函数定义

只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但与该虚函数具有相同的参数(包括个数和类型)和函数返回值类型的同名函数. 根据什么考虑是否把一个成员函数声明为虚函数? ①  看成员函数所在的类是否会作为基类 ② 看成员函数在类的继承后有无可能被更改功能,如果希望更改其功能的,一般应该

为什么 构造函数、内联函数、静态函数和友元函数不能是虚函数

构造函数为什么不能是虚函数 C++ 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数.简单来说就是:虚函数的执行依赖于虚函数表.而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表.而在构造对象期间,虚函数表还没有被初始化,将无法进行

转 C++构造函数、析构函数、虚函数之间的关系

C++构造函数.析构函数.虚函数之间的关系 1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了.2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类.3. 有虚函数的类,几乎可以确定要有个虚析构函数.4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的.5. 析构函数的异常退出会导致析构不完全,从而有内存泄露.最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作.6.

C++中不能声明为虚函数的有哪些函数

常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思,因此编译器会在编译时邦定函数. 多态的运行期行为体现在虚函数上,虚函数通过继承方式来体现出多态作用,顶层 函数不属于成员函数,是不能被继承的2.为什么C++不支持构造函数为虚函数? 这个原因很简单,主要是从语义上考虑,所以不支持.因为构造函数本来就是为了明

23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数

在C++中,继承方式共有3种: public继承 -指父类的成员(变量和函数)访问级别,在子类中保持不变 private继承 -指父类的成员,在子类中变为private私有成员. -也就是说子类无法访问父类的所有成员 protected继承 -指父类的public成员 ,在子类中变为protected保护成员,其它成员级别保持不变 <span "="" src="https://images2018.cnblogs.com/blog/1182576/20180

继承中的虚函数、纯虚函数、普通函数

一.虚函数 被virtual关键字修饰的类成员函数就是虚函数.虚函数的作用就是实现运行时的多态性,将接口与实现分离.简单理解就是相同函数有着不同的实现,但因个体差异而采用不同的策略. 基类中提供虚函数的实现,为派生类提供默认的函数实现.派生类可以重写基类的虚函数以实现派生类的特殊化.如下: class Base{ public: virtual void foo() { cout<<"Base::foo() is called"<<endl; } }; clas

单继承与多继承中的虚函数表和虚函数指针

首先,我们了解一下何为单继承,何为多继承?? 单继承:一个子类只有一个直接父类. 多继承:一个子类有两个或多个直接父类. 单继承中的虚函数表分析: 示例程序: #include <iostream> using namespace std; typedef void(*FUNC)(); class Base { public: virtual void func1() { cout << "Base::func1()" << endl; } virt

C++中虚函数和纯虚函数的作用与区别-详解

虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数! 虚函数 引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数. class Cman { public: virtual void Eat(){--}; void Move(); private: }; class CChild : public CMan { public: virtual void

C++中拷贝构造函数和赋值函数被调用的时机

一.拷贝构造函数被调用的时机: 1. 当用类的一个对象去初始化该类的另一个对象(或引用)时系统自动调用拷贝构造函数实现拷贝赋值. 2. 若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数. 3. 当函数的返回值是类对象时,系统自动调用拷贝构造函数. 二.赋值函数被调用的时机: 当用一个对象赋值给另一个对象时 注意一.二中初始化和赋值的区别 C++中拷贝构造函数和赋值函数被调用的时机,布布扣,bubuko.com