对于变量其实对应的就是内存,而内存并没有表明一定是什么数据类型,所以判断变量是否是一个指针其实是一个参数类型匹配问题,在C++中支持函数的重载,那么不同的函数因为参数的不同从而匹配不同函数调用过程。
编译器在进行函数匹配调用的时候会遵循如下优先级:
重载函数 > 函数模板 > 可变参数。
#include <iostream>
void Test(int a)
{
std::cout<<"Normal Function"<<std::endl;
}
template<typename T >
void Test(T a)
{
std::cout<<"Template Function"<<std::endl;
}
void Test(...)
{
std::cout<<"... Function"<<std::endl;
}
int main(int argc, char** argv)
{
Test(100);
Test(1, 100);
Test(100.1);
return 0;
}
有前面的语法基础以后,我们便可以利用可变参数与函数模板来进行相关程序设计进而判断一个变量是否为指针了。
#include <iostream>
template<typename T >
bool isPtr(T * a)
{
return true;
}
bool isPtr(...)
{
return false;
}
class MyClass
{
};
int main(int argc, char** argv)
{
int *ptr = nullptr;
int var = 0;
MyClass mc;
if(isPtr(ptr))
{
std::cout<<"This is ptr"<<std::endl;
}
if(!isPtr(var))
{
std::cout<<"This is not ptr"<<std::endl;
}
if(!isPtr(mc))
{
std::cout<<"This is not ptr"<<std::endl;
}
return 0;
}
变参函数是C++从C中继承过来的,虽然这里传入类对象能正常编译运行,并得到正确结果。但这样做存在风险,编辑器在做代码静态检查时会报警告:warning: passing object of class type 'MyClass' through variadic function,因为类对象可能包含非POD(Plain Old Data)类型,这些类型不能通过变参函数来安全地复制和访问,触发对象的切割(slicing)问题,运行时可能发生意想不到的错误。
其实我们匹配到函数时已经可以区分了,能不能只进行匹配,不调用函数呢?当然可以,如下所示:
#include<iostream>
template<typename T >
char isPtr(T * a)
{
return '\0';
}
int isPtr(...)
{
return 0;
}
class MyClass
{
};
#define ISPTR(p) (sizeof(isPtr(p)) == sizeof(char))
int main(int argc, char** argv)
{
int *ptr = nullptr;
int var = 0;
MyClass mc;
std::cout<<"ptr is ptr: "<< ISPTR(ptr)<<std::endl;
std::cout<<"var is ptr: "<<ISPTR(var)<<std::endl;
std::cout<<"mc is ptr: "<<ISPTR(mc)<<std::endl;
return 0;
}
这里我们用了宏,编译时sizeof(isPtr(p))就能确定大小,这样就可以只匹配不调用函数。
原文链接:https://blog.csdn.net/caoshangpa/article/details/140562652