C++简单对象模型理解

首先,我们对如下简单的程序进行分析:

#include<iostream>
using namespace std;
class A{
    void fun(){cout<<"A fun"<<endl;}
};
class B{
    int a;
};
class C{
    int b;
    void fun(){cout<<"C fun"<<endl;}
};
class D{
    int c;
    void fun1(){cout<<"D fun1"<<endl;}
    void fun2(){cout<<"D fun2"<<endl;}
    void fun3(){cout<<"D fun3"<<endl;}
};
class E{
    int d;
    int e;
    int f;
    void fun();
};
int main(){
    cout<<"size of A : "<<sizeof(A)<<endl;
    cout<<"size of B : "<<sizeof(B)<<endl;
    cout<<"size of C : "<<sizeof(C)<<endl;
    cout<<"size of D : "<<sizeof(D)<<endl;
    cout<<"size of E : "<<sizeof(E)<<endl;
}
其运行结果如下:

size of A : 1
size of B : 4
size of C : 4
size of D : 4
size of E : 12

其具体数值无需关注,在不同的环境下所得的值也并不一样,但是其基本的模型的不会变的,我们看到B中并未声明函数,其大小为一个int的大小,而C、D中声明了不同数目的函数,其大小却还是一个int的大小,这是为什么呢?

原来在C++中,只会将成员变量定义在类中,而成员函数是单独定义在类外面的,也就是说只有成员变量是属于这个类的,这也就解释了为什么E的大小只是三个int的大小。那么问题就来了,既然成员函数不是定义在类中的,如果多个类定义了同样名称的函数,编译器是如何对其进行区分的呢?比如说下面这段程序:

#include<iostream>
using namespace std;
class A{
public:
    void fun(){cout<<"A fun"<<endl;}
};
class B{
public:
    void fun(){cout<<"B fun"<<endl;}
};
int main(){
    A a;
    B b;
    a.fun();
    b.fun();
}

这里我们来看一下这个程序反编译后的代码:


由此可以看出,在编译时两个fun()的名字其实是不一样的,这样不同的类调用各自的成员函数时就不会搞错了。

根据上面说的我们可以在此做个实验,比如说我有如下一段程序:

#include<iostream>
using namespace std;
class A{
public:
    A():i(10),j(20){}
    void getIJ(){cout<<"i "<<i<<" j "<<j<<endl;}
    int i;
private:
    int j;
};
int main(){
    A a;
    int *p=(int*)&a;
    cout<<"*p "<<*p<<endl;
    a.getIJ();
    *p=30;
    a.getIJ();
    p++;
    cout<<"*p "<<*p<<endl;
    *p=40;
    a.getIJ();
}
大家可以先自己想一下结果会是什么,我这里就直接给出运行结果了


大家可以看到,当我将对象的指针给到一个int的指针后,我不仅可以访问并修改其public的成员变量,还可以访问并修改其private的成员变量。这是因为A类的对象中总共有两个东西,就是i和j,它们的地址是挨着的,当我用p++时自然就会指向下一个变量,而其变量是public还是private只会在编译时检查,只要一旦编译通过,那么再对其private的成员进行修改它也不知道了。

弄清楚这个后,我们再来看一下下面这段程序:

#include<iostream>
using namespace std;
class A{
    virtual void fun(){cout<<"A fun"<<endl;}
};
class B{
    int a;
};
class C{
    int b;
    virtual void fun(){cout<<"C fun"<<endl;}
};
class D{
    int c;
    virtual void fun1(){cout<<"D fun1"<<endl;}
    virtual void fun2(){cout<<"D fun2"<<endl;}
    virtual void fun3(){cout<<"D fun3"<<endl;}
};
class E{
    int d;
    int e;
    int f;
    virtual void fun(){cout<<"E fun"<<endl;}
};
int main(){
    cout<<"size of A : "<<sizeof(A)<<endl;
    cout<<"size of B : "<<sizeof(B)<<endl;
    cout<<"size of C : "<<sizeof(C)<<endl;
    cout<<"size of D : "<<sizeof(D)<<endl;
    cout<<"size of E : "<<sizeof(E)<<endl;
}

其运行结果如下图所示:

size of A : 8
size of B : 4
size of C : 16
size of D : 16
size of E : 24

此时当类中只定义一个虚函数时,其大小为8,当C与D中分别有不同个虚函数时,大小均为16,这又是为什么呢?

其实在C++中如果类中定义了虚函数,那么这个类中会有一个指针指向一张虚函数表,在这张虚函数表中存放着所有虚函数的地址,因此无论有多少个虚函数,这个类的大小都不会变化,因为它永远只是存储一个指向虚函数表的指针。

在此,上两张图来说明这个问题,比如说我们有下面这样一个类:


其模型应该是这个样子的:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值