栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++多态性

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++多态性

衍生:C/C++基类的析构函数为什么必须定义为虚函数?

在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生。
1)第一种情况:没有多态,创建派生类对象,基类的析构函数不是虚函数。

 #include
using namespace std;
class ClxBase{            //基类
public:
    ClxBase() {};
    ~ClxBase() {            //析构函数不是虚函数
        cout << "Output from the destructor of class ClxBase!" << endl;
    };
    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(){  
      //没有多态,派生类对象
      ClxDerived *p =  new ClxDerived;
      p->DoSomething();
      delete p;
      return 0;
      }
//运行结果
Do something in class ClxDerived!            
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!  

以上这段代码中基类的析构函数不是虚函数,在main函数中用派生类的指针去操作派生类的成员,释放指针P的过程是:先释放派生类的资源(执行~ClxDerived()) , 再释放基类资源(C++ primer里说编译器总是显示调用派生类对象基类部分的析构函数 ~ClxBase())。

2)第二种情况: 有多态,创建派生类对象,基类的析构函数不是虚函数

#include
using namespace std;
class ClxBase{       //基类
public:
    ClxBase() {};
    ~ClxBase() {         //析构函数不是虚函数
        cout << "Output from the destructor of class ClxBase!" << endl;
    };
 
    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 *p =  new ClxDerived;     //有多态
      p->DoSomething();
      delete p;
      return 0;
  } 
//运行结果
Do something in class ClxBase!
Output from the destructor of class ClxBase!

在以上这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作派生类的成员,释放过程: 只释放了基类的资源,而没有调用派生类的析构函数(因没有多态,静态绑定,只执行基类的析构函数~ClxBase() )。

一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半的现象从而造成内存泄漏。
在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。
析构函数自然也应该如此:如果它想析构子类中重新定义或新的成员及对象,当然也应该声明为虚的。

3)第三种情况:有多态,创建派生类对象,基类的析构函数是虚函数。
释放过程:先释放了继承类的资源,再调用基类的析构函数。

衍生:什么是纯虚函数?抽象类又是什么?

在虚函数的后面写上=0,则这个函数为纯虚函数。包含纯虚函数的类叫抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对相关。只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现了接口继承。

衍生:多态的原理

1)虚函数表

以上sizeof(Base)大小为8字节,除了成员,还多了一个_vfptr放在对象的前面(有些平台可能会放在对象后面,跟平台有关),对象中的这个指针称为虚函数表指针。一个含有虚函数的类中至少有一个虚函数表指针,虚函数地址要被放到虚函数表中。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977165.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号