类的内存分配以及通过内存创建对象

word版下载

1.需要论证的观点

1.1 类的类型的大小= 成员变量的大小的总和,成员函数无关。即

见例程1

1.2 成员函数存放在代码段,且不能被改变。对象只为成员变量在栈或堆上分配空间(不考虑virtual和继承等复杂点的情况)

见例程2

1.3 可以把栈或堆上的某个内存地址转化成(指向类的)指针,如果该内存区域恰好符合该类的对象的内存布局,那么这个指针就可以调用该类的方法了。【本文的重点】

见例程3

2. 例程

2.1 例程1

#include <stdio.h>
#include <iostream>
 
using std::cout;
using std::endl;

class Base
{
public:
Base(int _age = 100, int _height = 200, int _length = 300)
: age(_age), height(_height), length(_length)
{}

~Base()
{}
void print() {   cout<<"age="<<age<<endl;   cout<<"height="<<height<<endl;   cout<<"length="<<length<<endl; }
size_t get_size() {   
return sizeof(age) + sizeof(height) + sizeof(length); } private: int age; int height; int length; }; int main(int argc, char *argv[]) {   Base a;   cout<<"\tsizeof(class Base) ="<<sizeof(class Base)<<endl;   cout<<"\tsizeof(a) ="<<sizeof(a)<<endl;   cout<<"\tget_size() ="<<a.get_size()<<endl;   cout<<"conclusion: sizeof(class T) == sizeof(t) == sizeof(variable0) + sizeof(variable1) + ...... + szieof(variableN)"<<endl;   return 0; }

结果

sizeof(class Base) =12

sizeof(a) =12

get_size() =12

conclusion: sizeof(class T) == sizeof(t) == sizeof(variable0) + sizeof(variable1) + ...... + szieof(variableN)

结论

论证了观点1.1

2.2 例程2

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;

class Base

{
public:
Base(int _age = 100, int _height = 200, int _length = 300)
: age(_age), height(_height), length(_length)
{}

~Base()
{}

void print()

{
    cout<<"content:"<<endl;
    cout<<"\tage ="<<age<<endl;
    cout<<"\theight ="<<height<<endl;
    cout<<"\tlength ="<<length<<endl;

    int *p = &length;

    cout<<"\t *(p+1)="<<*(p+1)<<"\tthe next content of length"<<endl;

}

void print_address()

{
    cout<<"address:"<<endl;
    cout<<"\tthis ="<<this<<endl;
    cout<<"\t&age ="<<&age<<endl;
    cout<<"\t&height ="<<&height<<endl;
    cout<<"\t&length ="<<&length<<endl;
    cout<<"\t--------------"<<endl;
    cout<<"Code Segment address:"<<endl;
 
    printf("\t&Base::print =%p\n", &Base::print);
    printf("\t&Base::print_address=%p\n", &Base::print_address);
}

 

private:
    int age;
    int height;
    int length;
};

int main(int argc, char *argv[])
{
    Base a;
    a.print();
    cout<<endl;

    a.print_address();

    printf("\tmain =%p\n", main);

    //write into Code Segment

    void *pf = (void*)&Base::print;
    int *pfun = (int*)pf;
    *pfun = 1;//Segmentation fault
    return 0;

} 

 

 

结果

content:

age     =100

height     =200

length     =300

*(p+1)    =134515771 the next content of length

stack

address:

this         =0xbfea383c

&age     =0xbfea383c

&height     =0xbfea3840

&length     =0xbfea3844

--------------

Code Segment address:代码段

&Base::print     =    0x804896c

&Base::print_address     =     0x8048a90

main     =    0x8048830

Segmentation fault (core dumped)//因为代码段是只读的,所以不能写

结论

内存分布如图所示

2.3 例程3

#include <stdio.h>
#include <iostream>
#include <typeinfo>

using std::cout;
using std::endl;

class Base

{
public:

Base(int _age = 100, int _height = 200, int _length = 300)
: age(_age), height(_height), length(_length)
{}
~Base()
{}

void print()

{
    cout<<"-->Base::print()"<<endl;
    cout<<"\tage ="<<age<<endl;
    cout<<"\theight="<<height<<endl;
    cout<<"\tlength="<<length<<endl;
    cout<<"<--Base::print()"<<endl;
}

private:
    int age;
    int height;
    int length;
};

int main(int argc, char *argv[])
{
    Base *bp = new Base();
    bp->print();

    cout<<"********************************************"<<endl;
    cout<<"create Base by new int[3]"<<endl;
    cout<<"********************************************"<<endl;

    int *pi = new int[3];
    pi[0] = 400;
    pi[1] = 500;
    pi[2] = 600;

    Base *bp2 = (Base*)pi; //该内存区域的首地址转换成指向Base的指针

    bp2->print();//调用Base的方法

    return 0;
} 

 

 

结果

-->Base::print()

age     =100

height    =200

length    =300

<--Base::print()

********************************************

create Base by new int[3]

********************************************

-->Base::print()

age     =400

height    =500

length    =600

<--Base::print()

结论

通过手动构造一块内存区域,然后把该内存区域的首地址转换成指向Base的指针,就可以调用Base的方法了。

posted @ 2014-04-22 07:27  loverszhaokai  阅读(1247)  评论(0编辑  收藏  举报