我们知道用malloc函数申请一块内存后返回的是一个void指针,void指针又叫无类型指针,我们可以把它看成一个纯粹的指针,不指明它指向任何类型,但它可以转化成其他任何类型的指针.这其实很好理解,出于通用性考虑malloc申请了一块地址后然后用一个指针指向内存的首地址.因为不知道你申请内存给哪种类型.所以由你自己转换去.
其实我们从类的继承来考虑就比较容易理解.在MFC中所有类都继承自CObject,在C#中所有类继承自object.这样用object可以代表任何类.可以直接把任何类型赋值给object类型.
object ob = anyClass;所有void指针就像object一样,而其他指针就像任何类一样.不过要倒过来把object转换成其他任何类的话得强制性转换,而且如果类型不匹配也是不会成功的.
但任何指针之间都可以任意的转换.这是因为所有指针在内存中都一样的,32位系统中全部都是占4个字节,里面保存着一个内存地址.当然如果你把int指针转换成double的话读出来的数是个错误的数.但它们的转换是可以成功转的。
int num = 888;
int* pNum = #
void* pVoid = #
cout<<pNum<<pVoid; //打印的结果一样,pNum,pVoid都是保存着num首地址的值.
但是void指针只能是做指针用,不能进行一些操作,比如取值,加操作
比如*pNum, pNum++是可以的.但*pVoid,pVoid会出错.这很好理解.用*取值时必须知道啥类型才能知道要把几个字节一起读出来处理,++也一样,知道是啥类型才知道加的实际上的几.void它没表明指向任何类型自然没法去做这样的操作.
在C#中如果要让某个函数可以传任何类型的参数进去就用object做形参.比如void Function(object one, object two). arraylist是object类型的数组,所以你能往里面添加任何类型进去.那在C++中,如果某个函数需要允许传任意类型的指针做参数,返回任意类型的指针就可以用void指针
void* Function(void* one, void* two);
函数指针
我们知道void指针可以代表任意类型的指针,那它能代表函数指针吗.
比如 void (*pFun)(int num); //pFun是个函数指针
void* pVoid = pFun; //有些编译器里可以成功转换的,有些编译器会出错.因为函数指针其实也是指针来着,里面同样也只保存着地址值.
有些编译器之所以不让这样转换是出于这样的原因.
函数指针为调用函数的另一种方法,函数指针的内容可以修改,而函数指着指向的内容不能修改。但是void *指针指向的东西,是可以修改的。这样就破坏了c++内部的安全体系,应该被禁止.
不过其实这理由也不够充分拉,大不了用个常量指针,const void* pVoid = pFun;所以在这一点上不同编译器就没达成一致了啊.不过既然有这样的争议,就尽量别用void指针就指向函数得了.
我们用函数指针时会发现函数名貌似也像个指针了
例如
void Function(int num) { }
void (*pFun)(int);
pFun = Function;
int no = 777;
(*pFun)(no);
Function(no);
上面直接用函数名调用函数和用函数指针调用达到的效果完全一样.莫非函数名也是个指针?
你用cout<<Function;试下,会发现打印出来的是个地址值.跟cout<<pFun;一样.
其实函数名不是指针,它就跟数组名一样.是一个右值,是能赋予指针的一个值,但它本身不能被赋值.数组名是保存数组的首地址,函数名也是保存函数所在内存的首地址.