首先,我们对如下简单的程序进行分析:
#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++中如果类中定义了虚函数,那么这个类中会有一个指针指向一张虚函数表,在这张虚函数表中存放着所有虚函数的地址,因此无论有多少个虚函数,这个类的大小都不会变化,因为它永远只是存储一个指向虚函数表的指针。
在此,上两张图来说明这个问题,比如说我们有下面这样一个类:
其模型应该是这个样子的: