一个将类的构造函数调用识别成函数指针的问题

原创 2007年09月13日 12:35:00

  

Modern C++ Design第二章第一节,有一个关于定制编译器错误提示的例子:

template<bool> struct CompileTimeChecker 
{
    CompileTimeChecker(...);    
//一个接受任何参数的构造函数
};
template
<> struct CompileTimeChecker<false> { };//特化false版本 


//定义一个宏,msg为用户传入的错误消息提示,expr为判断式,expr为false时编译期将出
//错,并显示错误信息。
#define STATIC_CHECK(expr, msg)/
{/
    
class ERROR_##msg{};/
    (
void)sizeof(CompileTimeChecker<(expr) != 0>(ERROR_##msg()));/
}

有了这个宏STATIC_CHECK后,可以用来实现一个安全的指针类型转换模板函数,它检查目标类型的大小,如果目标类型小于原始类型,则在产生一个编译期错误,并显示我们自定义的错误提示:

template<typename To,typename From>
To Safe_reinterpret_cast(From 
&from)
{
    STATIC_CHECK(
sizeof(From) <= sizeof(To),
                  Destination_Type_Too_Narrow);
//定义错误提示信息
    return reinterpret_cast<To>(from);//如果宏验证通过表示可以安全转换
};
int main()
{
    
int *pa=0;
    
char c=Safe_reinterpret_cast<char>(pa);//将int指针转换成为char,根
                  // 据Safe_reinterpret_cast的定义,这里将不能通过编译
    return 0;
}

 

VC6.0下编译,提示:Error: cannot convert ERROR_Destination_Type_Too_Narrow to CompileTimeChecker<false>,我们定制的提示消息已经出现在Error中了。

 
这是个小技巧,CompileTimeChecker<true>这个特化类有一个可接受任何参数的的构造函数,这意味着当宏STATIC_CHECKexpr参数表达式在编译期评估为true时,(void)sizeof(CompileTimeChecker<(expr) != 0>(ERROR_##msg()))就有效,相当于调用CompileTimeChecker<true>接受一个类ERROR_##msg对象作为参数的构造函数
 
如果expr结果为false时,就会有编译期的错误发生:编译器找不到类CompileTimeChecker<false>接受一个参数的构造函数,从而显示错误信息。
 
这个STATIC_CHECK宏不会生成任何对象或指令造成运行时的开销,所有的检查都是在编译期完成。并且还能定制错误提示以方便找错,相对于晦涩难懂的模板编译错误提示,这可算得上非常不错了。
 
但是,当我将这些代码移植到VS2005却出现了问题,提示信息如下:
error C2066: 转换到函数类型是非法的
error C2070: CompileTimeChecker<false>
( Safe_reinterpret_cast::ERROR_Destination_Type_Too_Narrow (__cdecl *)(void) )

分析了一下错误信息,错误出在这一句:

(void)sizeof(CompileTimeChecker<(expr) != 0>(ERROR_##msg()));

原来编译器并没有按照我们的意思将ERROR_##msg()解释成调用类ERROR_##msg的默认构造函数来生成一个临时对象当作实参。却错误的将其解释成一个函数指针,一个没有参数,返回类型为ERROR_##msg类型的函数指针ERROR_Destination_Type_Too_Narrow (__cdecl *)(void)

 
为了解决这个问题,我们需要提供给编译器更多的信息,以使编译器能够正确的用ERROR_##msg()生成一个临时对象。
一个解决方法是用类名作限定符显示的调用构造函数:
(void)sizeof(CompileTimeChecker<(expr) != 0>(ERROR_##msg::ERROR_##msg()));
 
另一个方法是加上一个取地址操作符,因为取地址运算符只能做用于对象,这样编译器就知道ERROR_##msg()构造的是一个对象而不是定义一个函数指针了。
(void)sizeof(CompileTimeChecker<(expr) != 0>(&ERROR_##msg()));//这样就OK
现在提示信息变成:
法从”Safe_reinterpret_cast::ERROR_Destination_Type_Too_Narrow *__w64转换为”CompileTimeChecker<false>”

线程的封装技巧:把任意类的成员函数指针作为参数

线程的封装很简单,并没有多少东西,但是如果我告诉你,我封装的这个线程类里有个成员函数Start,作用是开启线程运行,可以这样调用:class a{public: DWORD ThreadFunca(L...
  • ringphone
  • ringphone
  • 2004年10月18日 13:48
  • 7252

解决iOS工程被Xcode识别成Mac工程的问题

亲测有效: [题外介绍:其实本宅也是一名程序员,各种经验和问题总结也不少,只是工作比较忙,很少在网上发文。本着互联分享精神,但各种网站账号太多,不一一发了]首先,这种问题一般出现在拷贝工程到另一台M...
  • lybeen2007
  • lybeen2007
  • 2017年08月25日 11:19
  • 248

函数指针的赋值与调用

问:先定义了个函数: int function(int a, int b) { .......... } main函数里面有个函数指针 问题1:那么下面两种对函数指针的赋值哪个是正确的,还...
  • zhangzhi123456789
  • zhangzhi123456789
  • 2015年10月19日 18:34
  • 6652

函数指针与指针函数以及结构体调用函数的方法

以前忘记在哪见过见过C语言中:结构体通过指针的方式调用函数的方法,就一直找,找了半天,同时发现自己对函数指针和指针函数这两个概念没搞清楚。下面先说一下两者的区别。再者就是说一下结构体是如何通过函数指针...
  • lg2lh
  • lg2lh
  • 2012年02月08日 13:49
  • 12598

带参数的main函数,应该怎样运行呢

关于给main函数传递参数问题!!!在Linux环境下, 一个程序main函数有参数,举报|2013-06-08 16:22epdc147 | 分类:C/C++ | 浏览550次那么linux命令行运...
  • u013176681
  • u013176681
  • 2014年08月18日 11:41
  • 2053

空格和‘\n’被吃问题

有关scanf和cin输入字符的问题, 还有gets()和getline()(总结一下scanf和cin使用时需要注意的事项) 今天刷题遇到的问题:定义一个6*5的字符数组,用scanf一个...
  • zhangxiaoduoduo
  • zhangxiaoduoduo
  • 2017年04月20日 19:41
  • 146

构造函数能否调用virtual 虚函数

之前有看到在Effective C++中提及,在构造函数里面是否可以调用虚函数。在书中是明前表示不建议我们这么干的。原因也很明确,就是在构造函数中,是无法执行到派生类中对应的函数接口的。但是,是否真的...
  • helinlin007
  • helinlin007
  • 2016年01月14日 23:52
  • 2128

C++如何声明类成员函数指针或类成员变量指针(A::*)

例如有如下类,class A { int mem; int* func(void) { //... } };怎么声明类A的成员函数指针或成员变量指针呢?...
  • yockie
  • yockie
  • 2016年06月30日 01:23
  • 2386

类里面的成员函数指针使用

先看代码 #include using namespace std; typedef void (*func)(); //含简单的定义一个函数指针,很容易用这个方法来实现指令,用作各种h...
  • apengjiang
  • apengjiang
  • 2011年12月22日 21:07
  • 5157

linux C编程(五)函数指针与函数调用

函数指针函数指针,首先是一个指针,只不过该指针指向的是函数,而不是变量。#include int max(int x,int y) { return (x>y)?x:y; } int main()...
  • u012177034
  • u012177034
  • 2016年08月25日 22:45
  • 1433
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个将类的构造函数调用识别成函数指针的问题
举报原因:
原因补充:

(最多只允许输入30个字)