例一:
cout<<&f<<endl;
cout<<&f[0]<<endl;
int f[4]={111,222,333,444};
cout<<f<<endl;cout<<&f<<endl;
cout<<&f[0]<<endl;
cout<<(f+1)<<endl;
cout<<&f[1]<<endl;
cout<<&f[1]<<endl;
cout<<((int*)&f+1)<<endl;
cout<<(&f+1)<<endl;
cout<<(&f+1)<<endl;
上述代码的运行结果为:
可以看出取址符&去掉了指针的类型,对于任意变量取地址,如果直接+1,经过测试一般情况下是增加了16.
把这些地址看做指针,指针+1,代表移动了一个位的长度,所以可以看出((int*)&f+1),是在原始地址上增加了一个int,4位的长度。
比较下面的代码我们可以进一步看出这个区别:
cout<<((int*)&f+1)<<endl;
cout<<((double*)&f+1)<<endl;
所以通过指针访问f[2],下面三种方式都正确
cout<<f[2]<<endl;
cout<<*(f+2)<<endl;
cout<<*((int*)&f+2)<<endl;
cout<<*((int*)&f+2)<<endl;
下面2种方式都是错误的
cout<<*(&f+2)<<endl;
cout<<*((double*)&f+1)<<endl;//虽然得到的地址(double*)&f+1和(int*)&f+2是一致的。
而通过指针方式,我们可以访问到类的私有成员,在正规情况下这些私有成员是无法被访问到的。
class CBase
{
private:
int m_data1;
virtual void vfunc1(){cout<<"CBase vfunc1"<<endl;}
public:
int m_data2;
void func1(){cout<<"CBase func1"<<endl;}
void func2(){cout<<"CBase func2"<<endl;}
virtual void vfunc2(){cout<<"CBase vfunc2"<<endl;}
void set_data1(int m){m_data1=m;m_data2=889;}
};
class Cchild:public CBase
{
public:
int m_data1;
int m_data3;
void func2(){cout<<"Cchild func2"<<endl;}
void func3(){cout<<"Cchild func3"<<endl;}
virtual void vfunc2(){cout<<"Cchild vfunc2"<<endl;}
virtual void vfunc3(){cout<<"Cchild vfunc3"<<endl;}
};
/*class classC:public classB
{
public:
int m_data1;
int m_data4;
void func2(){cout<<"class c"<<endl;}
virtual void vfunc1(){}
};*/
void main()
{
cout<<sizeof(CBase)<<endl;//结果为什么是12,是因为2个int,加一个虚函数表指针
cout<<sizeof(Cchild)<<endl;//结果是20,是因为4个int,加一个虚函数表指针
CBase a;
Cchild b;
a.set_data1(888);
//public成员可以这样访问
cout<<a.m_data2<<endl;
//而私有成员无法这样访问
//cout<<a.m_data1<<endl;//错误
//但可以这样访问私有成员
cout<<*((int*)&a+2)<<endl;
//在继承类中,一般的函数(非虚函数)被同名函数所隐藏,而并没有覆盖他,
b.func2();//我们直接调用func2得到的是Cchild中的func2
b.CBase::func2();//这样我们可以把隐藏的fun2唤出
//要访问b中从CBase继承而来的私有虚函数vfun1;
cout<<"虚函数表的地址指针"<<(int*)(&b)<<endl;
cout<<"虚函数表的地址"<<(int*)*((int*)(&b))<<endl;
cout<<"第一个虚函数的地址"<<((int*)*((int*)(&b))+0)<<endl;
cout<<"第二个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
cout<<"第三个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
typedef void(*PFun)();//定义函数指针类型
PFun fun1;
fun1=(PFun)*((int*)*((int*)(&b))+0);
fun1();//CBase::vfun1;成功访问了私有的虚函数
((PFun)*((int*)*((int*)(&b))+0))();//和上面的效果是一样的.
(((PFun)*((int*)*((int*)(&b))+0)))();//访问第二虚函数个函数注意是Cchild::vfun2(),而不是CBase::vfun2(),
//在b中Cbase::vfun2已经被Cchild::vfun2所覆盖。
{
private:
int m_data1;
virtual void vfunc1(){cout<<"CBase vfunc1"<<endl;}
public:
int m_data2;
void func1(){cout<<"CBase func1"<<endl;}
void func2(){cout<<"CBase func2"<<endl;}
virtual void vfunc2(){cout<<"CBase vfunc2"<<endl;}
void set_data1(int m){m_data1=m;m_data2=889;}
};
class Cchild:public CBase
{
public:
int m_data1;
int m_data3;
void func2(){cout<<"Cchild func2"<<endl;}
void func3(){cout<<"Cchild func3"<<endl;}
virtual void vfunc2(){cout<<"Cchild vfunc2"<<endl;}
virtual void vfunc3(){cout<<"Cchild vfunc3"<<endl;}
};
/*class classC:public classB
{
public:
int m_data1;
int m_data4;
void func2(){cout<<"class c"<<endl;}
virtual void vfunc1(){}
};*/
void main()
{
cout<<sizeof(CBase)<<endl;//结果为什么是12,是因为2个int,加一个虚函数表指针
cout<<sizeof(Cchild)<<endl;//结果是20,是因为4个int,加一个虚函数表指针
CBase a;
Cchild b;
a.set_data1(888);
//public成员可以这样访问
cout<<a.m_data2<<endl;
//而私有成员无法这样访问
//cout<<a.m_data1<<endl;//错误
//但可以这样访问私有成员
cout<<*((int*)&a+2)<<endl;
//在继承类中,一般的函数(非虚函数)被同名函数所隐藏,而并没有覆盖他,
b.func2();//我们直接调用func2得到的是Cchild中的func2
b.CBase::func2();//这样我们可以把隐藏的fun2唤出
//要访问b中从CBase继承而来的私有虚函数vfun1;
cout<<"虚函数表的地址指针"<<(int*)(&b)<<endl;
cout<<"虚函数表的地址"<<(int*)*((int*)(&b))<<endl;
cout<<"第一个虚函数的地址"<<((int*)*((int*)(&b))+0)<<endl;
cout<<"第二个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
cout<<"第三个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
typedef void(*PFun)();//定义函数指针类型
PFun fun1;
fun1=(PFun)*((int*)*((int*)(&b))+0);
fun1();//CBase::vfun1;成功访问了私有的虚函数
((PFun)*((int*)*((int*)(&b))+0))();//和上面的效果是一样的.
(((PFun)*((int*)*((int*)(&b))+0)))();//访问第二虚函数个函数注意是Cchild::vfun2(),而不是CBase::vfun2(),
//在b中Cbase::vfun2已经被Cchild::vfun2所覆盖。
运行效果如图所示
.总结发成下面的图