C++ 没有类似Java反射机制,无法动态获取对象元信息,那么如何检测对象是否存在成员函数呢?
1. 检测是否存在特定成员函数
muduo框架中有这样一段代码:
vi muduo/base/Singleton.h
template<typename T> struct has_no_destroy { template <typename C> static char test(decltype(&C::no_destroy)); // 返回char template <typename C> static int32_t test(...); // 返回int const static bool value = sizeof(test<T>(0)) == 1; }; static void init() { value_ = new T(); // 判断是否存在no_destroy方法 if (!detail::has_no_destroy<T>::value) { ::atexit(destroy); } }
测试代码:
struct A { // empty }; struct B { int no_destroy; // 成员变量 }; struct C { int no_destroy(){} // 成员函数 }; void test() { // 匹配test(&A::no_destroy) 时,由于A没有no_destroy方法,理论上应该报错。编译器寻找下一个匹配test(...),因此返回0 bool p1 = has_no_destroy<A>::value; bool p2 = has_no_destroy<B>::value; bool p3 = has_no_destroy<C>::value; printf("%d %d %d\n", p1, p2, p3); // 输出 0 1 1 }
上文利用了c++ SFINAE(Substition Failure is not a error) 特性语法,即匹配失败不是错误。在进行模板特化,编译器会返回最佳匹配模板,避免失败。
2. 增强版本
上述代码,B的no_destroy成员也可以正常调用,那如何只检测成员函数呢?
成员函数要用对象来调用,可用declval构造对象。
struct check_no_destroy { /** * 1. T 对象 * 2. U 获取T::no_destroy()返回值 * 3. 返回值类型为int */ template <typename T, typename U = typename std::decay<decltype(std::declval<T>().no_destroy())>::type, typename = typename std::enable_if<std::is_same<int, U>::value>::type> static std::true_type Test(int); template <typename> static std::false_type Test(...); }; template <typename T> struct has_no_destroy : public decltype(check_no_destroy::Test<T>(0)) { }; void test() { /* std::true_type = integral_constant<bool, true>; 显示值::value */ bool p = hash_no_destroy<D>::value; cout << p << endl; // 1 }
相关推荐
介绍了 C++的 I/O( 输入输出 )问题,本文结构清晰,讲解简单易懂,对 C++ 的流模型作为细致...入部分,介绍了 cin 流,输入时的错误检测机制,及使用输入流类的成员函数进行输入的函数。最后详细介绍了文件的 输入输出
问题提出 最近工作中遇到这样一个需求:实现一个ToString函数将类型T转换到字符串,如果类型T中含有同名方法ToString...其中用到了一个C++17的std::void_t,考虑到目前C++17还没得用,这个实现只作参考之用(事实上C++
模板类实现普通成员函数作为回调函数,deelx正则表达式库的使用示例,交互式控制台调试模块以及磁盘检测模块的封装类。转载请保留版权。
04_类中不写成员函数易犯错误模型 05-易犯错误模型-为什么需要成员函数(补充资料)-传智扫地僧 06_课堂答疑类中写成员函数_调用的时才会执行 07_程序设计方法发展历程 08_C语言和C++语言的关系_工作经验分享 09_...
使用编写的串口类文件,实现简单的C++串口通信MFC程序,可以实现可用串口检测,串口属性配置,开启关闭串口,通过回调函数将串口byte数据传递到其他类成员函数中使用
面试题4:是否可类的每个成员函数都声明为虚函数,为什么。 c++编译器多态实现原理 6 面试题5:构造函数中调用虚函数能实现多态吗?为什么? c++编译器多态实现原理 6 面试题6:虚函数表指针(VPTR)被编译器初始...
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会...8.3.2 在类外定义成员函数 8.3.3 inline成员函数 8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...
5.19.2 数值调节钮成员函数 251 5.20 Visual C++ 2010 GroupBox控件简介与开发 251 5.21 Visual C++ 2010 Data Time Picker控件简介与开发 252 5.21.1 创建日期和时间选择器控件 253 5.21.2 访问嵌入的月历控件 253 ...
23.4 const成员函数与mutable 23.5 volatile成员函数 23.6 explicit构造函数 23.7 成员初始化语法 23.8 利用关键字asm 23.9 连接说明 23.10 基于数组的I/O 23.11 C与C++的区别 第24章 标准模板库 24.1 STL概述 24.2 ...
在MFC中对消息的处理利用了消息映射的方法,该方法的基础是宏定义实现,通过宏定义将消息分派到不同的成员函数进行处理。下面简单讲述一下这种方法的实现方法: 代码如下 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd...
面试题7:C++的空类有哪些成员函数 8.3 构造函数和析构函数 面试题8:构造函数能否为虚函数 面试题9:简述子类与父类的析构、构造函数的调用顺序 面试题10:编写类String 的构造函数、析构函数和赋值函数 8.4 拷贝...
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会...8.3.2 在类外定义成员函数 8.3.3 inline成员函数 8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...
1.5.4 函数级的try块 1.6 标准异常 1.7 异常规格说明 1.7.1 更好的异常规格说明 1.7.2 异常规格说明和继承 1.7.3 什么时候不使用异常规格说明 1.8 异常安全 1.9 在编程中使用...
5.2.2 CBitmap中的成员函数 193 5.2.3 应用DDB显示图像 193 5.2.4 应用DDB显示大图像 195 5.3 进一步了解DIB 203 5.3.1 DIB的结构 203 5.3.2 DIB信息段 203 5.3.3 位图数据 205 5.3.4 与DIB有关的函数 206 5.4 本章...
SURF即Speeded Up Robust Features加速鲁棒特征;...类SURF中成员函数create()参数说明: static Ptr<SURF> create( double hessianThreshold=100,//SURF中使用的hessian关键点检测器的阈值 int nOct
面向对象程序设计 (C++) 实 ... 构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而 是在建立对象时自动执行。 构造函数的名字必须与类名同名,而不能由用户任意命名,以便编译系统能识别它
3.4.7 妨碍继承的成员函数 3.5 派生赋值问题 3.6 允许入侵(用户修改源代码)继承 3.7 总结 3.8 练习 3.9 参考文献和相关资料 第4章 效率 4.1 效率和重用性 4.2 程序创建时间 4.2.1 编译时间 4.2.2 实例...