C++ 类的本质 札记
原文地址:http://hi.baidu.com/chzhao007/blog/item/e9dbc5ac1191bc034b36d6df.html
前几天,我竟被只小鸟小觑了一下,我承认本人blog中张贴出来的代码确实一般,所以我得在此在重审一下:本人张贴出来的代码都不是本人最终代码!
本人blog中到现在确实用C写的代码很多,但不代表本人不崇尚C++的对象编程,只不过本人现在从事的许多方面用C和汇编搞起来比较方便,所以用C写东东比起C++来随手。为了使本人blog阐述的东东近于完善,在此就写下本人对C++类的一点点本质认识。在此再次重审:本人blog不代表本人现在真实水准。谁都要有点看家本事,否则在这社会上还真不好混,做为看家本事,一般是不外泄的哦。
本人在此不讨论理论上什么叫C++类(什么类代表汽车,鸭子的不会在此文中找到),在此只在机码层看看类到底是如何实现和运行的。
在这里我先定义一个测试用的类
class one{
public:
one():a(10){}
~one(){}
void seta(int a) { this->a = a;}
int geta(void) { return a; }
void setb(int b) { this->b = b;}
int getb(void) { return b;}
private:
int a,b;
};
接下来让我们定义一个类元素
one testone;
下面让我们看看定义的这个testone在内存中占多大
std::cout<<sizeof(testone)<<"\n"; //运行之后你会发现 testone在内存中只有8个字节 就是两个int的大小
在此我们完全可以认为 one 等同于
struct{
int a;
int b;
}one;
如果你很想耍帅的话 你可以这样动态声明一个类 test* one = (one *)new int(2);
现在让我们再定义一个one元素 one testtwo; 同样testtwo的大小也是8字节。现在我们就有一个疑问喽,testone与testtwo大小相同但不是同一个实体,它们是如何和 one() ~one() seta() geta()等函数联系到一起的?
现在让我们在汇编级看看
testone.seta(1);
00401098 6A 01 push 1
0040109A 8D 4D EC lea ecx,[ebp-14h]
0040109D E8 72 FF FF FF call @ILT+15(one::seta) (00401014)
testtwo.seta(2);
004010A2 6A 02 push 2
004010A4 8D 4D E4 lea ecx,[ebp-1Ch]
004010A7 E8 68 FF FF FF call @ILT+15(one::seta) (00401014)
我们发现 testone和testtwo调用它们各自的seta时用到同一个地址 00401014,在此可以肯定,同一个类one定义的元素共用类one定义的方法函数。
那么我们又可以推测出testone和testtwo的不同点是只有各自的int a\ int b 变量的地址不同了。在汇编码中我们又发现ebp - 14h和ebp - 1ch正好相差8字节。我的代码
one testone;
one testtwo;
定义的testone和testtwo是相挨着的,所以分内存时testtwo会紧跟testone之后。
在此我们可以总结一下了c++类的实现,编译器将
结构 struct{
int a;
int b;
}one;
与
一系列的函数方法
one():a(10){}
~one(){}
void seta(int a) { this->a = a;}
int geta(void) { return a; }
void setb(int b) { this->b = b;}
int getb(void) { return b;}
自动进行了捆绑。这就好比生产线,生产设备是固定的,只是进出的零件在换罢了,而这些零件是事先处理(声明)后与此生产线相配的一套零件。
通过以上本人对c++类本质的简述,想毕各位可以很轻松的用c语言实现c++的类了吧(只要在加入结构与方法的固化就O了)。
在此本人在多述几句,功夫高手草朩皆兵,万物皆刃。编程注重的是思想不要固化在你所学的语言之上,要学会万化自然。
完