C++对象模型详解 虚函数详解(一)

1、类对象基本知识

1.1常用结论

  • 成员函数不占类对象的内存空间。
  • 一个类对象至少占1字节内存空间
  • 成员变量是包含在每个对象中的,占字节的
  • 成员函数虽然也写在类定义中,但成员函数不占类对象的字节空间。也就是说,成员函数是跟着类走的,跟类对象没有关系,不管用这个类产生了多少个该类的对象。
// ModelTest1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>

class MyClass
{
   
public:
    void f();
    void f1();
public:
    //char m_char;
    int m_int;
};



int main()
{
   
    std::cout << "Hello World!\n";
    MyClass  a;
    int len = sizeof(a);
    printf("myclass len %d",len);


}
  • 静态成员变量不计算在对象的sizeof内。
  • 普通成员函数和静态成员函数不计算在sizeof内。
  • 虚函数不计算在对象的sizeof内,但虚函数会让对象的sizeof增加4字节以容纳指向虚函数表的指针。
  • 虚函数表是基于类的(跟着类走,不是基于对象的)。
  • 如果类中有多个数据成员(成员变量),编译器会进行内存字节对齐(如4字节对齐)
  • 任何类型指针char *p、int *q等,指针占用的内存大小是固定的。一般要么是4个字节(跟编译器和系统有关系)
// ModelTest1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

class MyClass
{
   
public:
    void f();
    void f1();
public:
    //char m_char;
    int m_int;
};

class CClass1
{
   
public:
    CClass1() {
   };
    virtual ~CClass1() {
   };
    virtual void vf1() {
   };
    
public:
    int GetValue()
    {
   
        return m_value;
    }

    static  int  GetStaticValue()
    {
   
        return  ms_value;
    }

private:
    int  m_value;
    static int  ms_value;

};


int main()
{
   

    CClass1 cc;
    int  len;
    len = sizeof(cc);
    std::cout << " class len:" << len;





    //std::cout << "Hello World!\n";
    //MyClass  a;
    //int len = sizeof(a);
    //printf("myclass len %d",len);

    //int c;
    //std::cin >> c;
    //char aaa[1000] = "safasdfa\Odef";
    //printf(aaa);
}

在这里插入图片描述

1.2 类成员的内存分布

// memeryLayout.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;

class MyClass
{
   
public:
    int m_i;
    static int m_si;
    //char m_cii;
    int m_j;
    static int m_sj;
    int m_k;
    static int m_sk;

    //12
private:
    //char m_ci;
    //char m_cj;
};

int MyClass::m_si = 0;
int MyClass::m_sj = 0;
int MyClass::m_sk = 0;

int main()
{
   
    std::cout << "Hello World!\n";

    //栈内存
    MyClass    mm;
    mm.m_i = mm.m_j = mm.m_k = 0;
    cout << " myClass size:"<<sizeof(MyClass)<<endl;
    printf("mm.m_i address = %p\r\n", &mm.m_i);
    printf("mm.m_j address = %p\r\n", &mm.m_j);
    printf("mm.m_k address = %p\r\n", &mm.m_k);

    printf("mm.m_si address = %p\r\n", &mm.m_si);
    printf("mm.m_sj address = %p\r\n", &mm.m_sj);
    printf("mm.m_sk address = %p\r\n", &mm.m_sk);

    //堆上
    cout << "*******************************"<<endl;
    MyClass* pmm = new MyClass();
    printf("pmm.m_i address = %p\r\n", &pmm->m_i);
    printf("pmm.m_j address = %p\r\n", &pmm->m_j);
    printf("pmm.m_k address = %p\r\n", &pmm->m_k);

    printf("pmm.m_si address = %p\r\n", &pmm->m_si);
    printf("pmm.m_sj address = %p\r\n", &pmm->m_sj);
    printf("pmm.m_sk address = %p\r\n", &pmm->m_sk);

     

}

在这里插入图片描述

  • 内存基本是连续的 每个int占 内存4个字节
  • 会出现内存对齐或者边界调整,(4字节或者其他) 可以使用
#pragma pack (1)   //1字节对齐

1.2.1成员变量的偏移值

// memeryLayout.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;

class MyClass
{
   
public:
    int m_i;
    static int m_si;
    //char m_cii;
    int m_j;
    static int m_sj;
    int m_k;
    static int m_sk;
public:
    void PrintMemeryOffset()
    {
   
        cout << "打印成员偏移量:" << endl;
        printf("MyClass::m_i =0x %d \r\n", &MyClass::m_i);    //要带上类名才是偏移量,  否则就是变量的物理地址
        printf("MyClass::m_j =0x %d\r\n", &MyClass::m_j);    //要带上类名才是偏移量,  否则就是变量的物理地址
        printf("MyClass::m_k =0x %d\r\n", &MyClass::m_k);    //要带上类名才是偏移量,  否则就是变量的物理地址
        printf("MyClass::m_pi =0x %d\r\n", &MyClass::m_pi);    //要带上类名才是偏移量,  否则就是变量的物理地址
        printf("MyClass::m_pj =0x %d\r\n", &MyClass::m_pj);    //要带上类名才是偏移量,  否则就是变量的物理地址
        printf("MyClass::m_si =0x %x\r\n", &MyClass::m_si);    //变量的物理地址

    }
    //12
private:
    //char m_ci;
    //char m_cj;
    int  m_pi;
    int  m_pj;

};

int MyClass::m_si = 0;
int MyClass::m_sj = 0;
int MyClass::m_sk = 0;

int 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值