C++中基类的虚函数的一些思考

来源:互联网 发布:js 数组合并去重 编辑:程序博客网 时间:2024/06/05 07:19

先看下述程序:

#include<iostream>using namespace std;class ClxBase{public:    ClxBase() {};    virtual ~ClxBase() {};    virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };};class ClxDerived : public ClxBase{public:    ClxDerived() {};    ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };     void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };};int main() {ClxBase *pTest = new ClxDerived;pTest->DoSomething();delete pTest;return 0;}
输出结果:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!

若是将基类中析构函数的virtual去掉,输出结果变成:
Do something in class ClxDerived!

也就是说,继承类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。

所以, c++中基类写成虚函数的作用当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。


c++中基类写成虚函数的作用

C++中的虚函数总结

避免在派生类中重新定义基类的非虚函数



c++中对虚函数的理解


C++支持多种形式的多态,从表现的形式来看,有虚函数、模板、重载等,从绑定时间来看,可以分成静态多态和动态多态,也称为编译期多态和运行期多态。


由上图可知,虚函数属于多态中的动态多态。

【动态多态】
动态绑定:在程序执行期间(非编译期)判断所引用对象的实际类型,根据其实际类型调用相应的方
法。
使用virtual关键字修饰类的成员函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实
现动态绑定。

虚函数的作用:虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。


#include<iostream>using namespace std;class Base{public:virtual void FunTest1(){cout << "Base::FunTest1" << endl;}};class Drived:public Base{public:virtual void FunTest1(){cout << "Drived::FunTest1" << endl;}};void FunTest(){Base b;Drived d;Base &rd = d;d.FunTest1();b.FunTest1();rd.FunTest1();}int main(){FunTest();system("pause");return 0;}

输出结果:

Drived::FunTest1
Base::FunTest1
Drived::FunTest1



总结:

1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3、只有类的非静态成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。
4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆
6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
7、最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)



原创粉丝点击