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

c++虚函数和vtab

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

c++虚函数和vtab

文章目录
  • 虚函数
    • 虚析构
    • 纯虚函数示例
    • overwrite
    • 虚函数原理和vtb
      • 虚函数示例代码
      • 虚析构示例代码
      • vtab示例代码

虚函数

虚函数主要用来解决基类指针指向派生类时实际指向基类的问题 问题示例

虚析构

虚析构是为了解决基类指针指向派生类时调用指针进行析构不能析构派生类可能导致内存泄漏问题 问题示例

纯虚函数示例

纯虚函数是基类为派生类专门声明的接口,因此派生类如果需要实例化则必须对该纯虚函数进行定义,否则定义不完整不能实例化。

类似纯虚类也是,专门用来提供派生类覆盖模板,派生类必须完全实现才能实例化。

overwrite
  • 用在基类函数后表示该函数必须被派生类进行重写

  • 用在派生类明确表示是对基类的函数覆盖,防止写错函数名或参数表

    此处实验实例化含未实现虚函数的对象实例化会报链接错误,即实例化的类中不能包含未被定义的函数

虚函数原理和vtb
  • 首先区分栈区,代码区,比如new class ,new出的只是类的成员变量部分,而函数在代码区
  • 如果一个类包含虚函数会在new出的对象开始部分增加一个指针大小的空间,用来存储vtab的地址
  • 如果一个类包含虚函数类的大小会增加(64位上前8后4)
  • 含虚函数的类首地址指向虚函数表,而同一个虚函数类同继承的不同实例指向同一个vtab,同一个虚函数的不同继承的实例指向不同vtab
  • 测试代码
虚函数示例代码
#include 
using namespace std;
class A{
    public:
        void Pt(){
            std::cout << "Pt A" << std::endl;
        }
};
class B:public A{
    public:
        void Pt(){
            std::cout << "Pt B" << std::endl;
        }
};
int main(int argc,char** argv){
    A* oa = dynamic_cast(new B);
    oa->Pt();//Pt A
    return 0;
}

返回顶部

虚析构示例代码
#include 
using namespace std;
class A{
    public:
        A(){std::cout << "construct A" << std::endl;}
        ~A(){std::cout << "disconstruct A" << std::endl;}
};
class B:public A{
    public:
        B(){std::cout << "construct B" << std::endl;buf = new char[50];}
        ~B(){std::cout << "disconstruct B" << std::endl;delete buf;}
    private:
        char* buf;
};
int main(int argc,char** argv){
    A* oa = dynamic_cast(new B);
    delete oa;
    
    return 0;
}

返回顶部

vtab示例代码
#include 
#include 
#include 
#include 

std::string to_hex(unsigned char* data, int len) {
    std::stringstream ss;
    ss << std::uppercase << std::hex << std::setfill('0');
    for (int i = 0; i < len; i++) {
        ss << std::setw(2) << static_cast(data[i]);
    }
    return ss.str();
}

class A{
    private: 
    int a;
    public:
    A():a(11){};
    void p();
};
class B{
    protected: 
    int a;
    public:
    B():a(11){};
    virtual void p(){ std::cout << "B Class"<< a << std::endl;};
};
class C:public B{
    public:
    void p(){std::cout << "C Class"<< a << std::endl;};

};
int main()
{
  A a1;
  unsigned char* p1 = reinterpret_cast(&a1);
  std::cout << to_hex(p1,sizeof(a1)) << std::endl;//0B000000
  std::cout <(&b1);
  std::cout << to_hex(pb1,sizeof(b1) ) << std::endl;//40204000000000000B0000009D7F0000
  std::cout <(&c1);
  std::cout << to_hex(pc1,sizeof(c1) ) << std::endl;//28204000000000000B0000009D7F0000
  std::cout <(&c2);
  std::cout << to_hex(pc2,sizeof(c2) ) << std::endl;//28204000000000000B0000009D7F0000
  std::cout < 

返回顶部

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

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

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