1. 背景

  在阅读到C++Primer第268页时发现其示例编写好后程序报错。

#include <iostream>
using namespace std;
class Debug
{
public:constexpr Debug(bool b = true) : hw(b), io(b), other(b){};constexpr Debug(bool h, bool i, bool o) : hw(h), io(i), other(o){};constexpr bool any(){return hw | io | other;}void set_io(bool b){io = b;}void set_hw(bool b){hw = b;}void set_other(bool b){other = b;}private:bool hw;bool io;bool other;
};int main()
{constexpr Debug io_sub(false, true, false);if(io_sub.any()){cerr << "print approptiate error messages" << endl;}constexpr Debug prod(false);if(prod.any()){cerr << "print an error message" << endl;}return 0;
}

报错提示

2. 基础相关知识(可跳过)

  1. 常量表达式。值不会改变并且在编译过程就能得到计算结果的表达式。
const int max_files = 20; // max_files是常量表达式
const int limit = max_files + 1; // limit是常量表达式
int staff_size=27; // staff_size不是常量表达式,因为staff_size不是常量
const int sz = get_size(); // sz不是常量表达式,因为get_size()结果未知
  1. constexpr变量。声明为constexpr的变量一定是一个常量,且必须用常量表达式初始化。
constexpr int mf = 20;
constexpr int limit = mf + 1;
const int *p1 = nullptr; //p1是指向常量的指针
int * const p2; //p2本身是常量
constexpr int *p3 = nullptr; // p3本身也是常量
  1. 字面值类型。算术类型、引用和指针属于字面值类型,自定义类、IO库、string类型不属于字面值类型。只有字面值类型才能声明constexpr。

  2. constexpr函数。能用于常量表达式的函数。其函数的返回类型和所有形参的类型都是字面值类型,函数体中必须有且只有一条return语句。constexpr函数不一定返回常量表达式。

constexpr int new_sz() {return 42;}
constexpr int foo= new_sz();
  1. 聚合类。当一个类满足以下条件时,该类便是聚合类:所有成员都是public;没有定义任何构造函数;没有类内初始值;没有基类和virtual函数。

  2. 字面值常量类。数据成员都是字面值类型的聚合类是字面值常量类,除此以外,满足以下所有条件的也是字面值常量类:数据成员都是字面值类型;类必须至少含有一个constexpr构造函数;若一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式,或者若成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数; 类必须使用析构函数的默认定义,该成员负责销毁类的对象。

3. 分析

  1. 由示例可知,io_sub和prod是constexpr变量。故io_sub和prod本身便是常量,其类型相当于const Debug
//constexpr Debug等价于 const Debug
constexpr Debug io_sub(false, true, false);
constexpr Debug prod(false);
  1. 成员函数any()是一个constexpr函数。在c++11标准下,constexpr函数是常量成员函数,在c++14标准下,constexpr函数不是常量成员函数。我的编译器默认constexpr函数不是常量成员函数。
constexpr bool any()
//c++11标准下等价于
bool any () const
//c++14标准下等价于
bool any()
  1. 常量对象io_sub在调用成员函数any()时,this=&io_sub。this的类型是Debug * const,指向Debug,而io_sub是const Dedug。一般指针的类型必须与其所指向对象的类型相匹配,故调用错误。prod同理也是如此。
io_sub.any()
prod.any()

4. 改正方法

  既然在默认c++标准下,constexpr函数不是常量成员函数,而io_sub和prod是常量对象,只能调用常量成员函数。那可通过以下2种方式将any()修改为常量成员函数:

  1. 在any()后加const使其成为常量成员函数。
constexpr bool any() const
{return hw | io | other;
}

运行结果

  1. 编译时使用c++11标准,是使constexpr函数默认是常量成员函数。

运行结果

5. 总结

  1. 声明为constexpr的变量一定是一个常量。
  2. 类中声明为constexpr的函数不一定是常量成员函数,这由编译的c++标准决定。编程时,最好根据自己需要主动添加const。
  3. 构造函数不能是常量成员函数,但字面值常量类的构造函数可以是constexpr函数。

作者:扶摇直上九万里wyh
链接:https://www.jianshu.com/p/8418ed751fb0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

C++Primer:字面值常量类调用函数错误(p268书中示例报错)相关推荐

  1. JQuery在IE中function ()报错函数未定义

    记录一次JQuery在IE中function ()报错函数未定义处理方式,这个问题还是经历太少,前前后后排查了一个小时才解决.网上搜了很多,但对自己的用处并不大, 因此贴出错误和解决方法及思路供大家参 ...

  2. 使用matlab中cell2mat报错:错误使用cat 要串联的数组的维度不一致

    使用matlab中cell2mat报错:错误使用cat 要串联的数组的维度不一致 从Excel中用readtable读取数据,因为默认每一列都是cell类型,想转成matrix类型方便使用. 在mat ...

  3. 【错误记录】Kotlin 编译报错 ( Class ‘Xxx‘ is not abstract and does not implement abstract member )

    文章目录 一.报错信息 二.解决方案 一.报错信息 Google Play 上架要求 Android 的编译版本 和 目标版本都要高于 30 才可以上传 ; 将 Android 的编译版本 和 目标版 ...

  4. 【错误记录】VMware 虚拟机报错 ( 向 VMWare 虚拟机中的 Ubuntu 系统拷贝文件时磁盘空间不足 ② | 删除交换空间 )

    文章目录 一.报错信息 二.解决方案 一.报错信息 在 [错误记录]VMware 虚拟机报错 ( 向 VMWare 虚拟机中的 Ubuntu 系统拷贝文件时磁盘空间不足 ) 博客中 , 给出了解决方案 ...

  5. 【错误记录】记录 Android 命令行执行 Java 程序中出现的错误 ( dx 打包 PC 可执行文件报错 | dalvik 命令执行 kotlin 编译的 dex 文件报错 )

    文章目录 前言 一.Android 命令行与 PC 可执行 JAR 文件不兼容 二.Android 命令行使用 dalvik 命令不能直接执行 Kotlin 编译的 dex 文件 前言 尝试在 And ...

  6. python2中的unicode_python2中的unicode()函数在python3中会报错:

    python2中的unicode()函数在python3中会报错:NameError: name 'unicode' is not defined There is no such name in P ...

  7. 金蝶osf接口开发_调用OSF接口取待办任务总数报错!急

    总部老师,好: 在调用OSF接口取待办任务总数报错 Method failed: HTTP/1.1 404 Not Found org.apache.commons.httpclient.HttpEx ...

  8. maven错误:unknow文件夹--报错:Failure to find xxx:pom:unknown

    maven错误:unknow文件夹--报错:Failure to find xxx:pom:unknown 我的问题原因 我的解决 具体过程 解决 我的问题原因 根本原因:这个依赖的版本号没有指定 我 ...

  9. 【k8s错误解决系列】kubelet报错too many open files

    [k8s错误解决系列]kubelet报错too many open files.md release author: ningan123 release time: 2022-08-12 报错日志 # ...

最新文章

  1. linux c http下载 带确认 进度条
  2. Struts2利用stream直接输出Excel
  3. Windows 2008 VS2008 IIS7 中调试Asp.net 2.0 两个问题
  4. 团队作业-Beta冲刺第二天
  5. How to determine if SAP CRM UI is extensible
  6. posix thread线程
  7. MongoDB 常用shell命令汇总
  8. Unity Excel转json且自动生成C#脚本
  9. MySQL5.7官网参考手册路径
  10. 输入数学函数c语言,C语言基本输入输出及数学函数.ppt
  11. [任天堂社长访谈之:Nintendo 3DS内置软件
  12. 淘宝返利模式的简单实现方法
  13. Supervisor 使用说明,轻松管理进程
  14. C++课程设计:学生管理系统
  15. 基于boost库的站内搜索引擎
  16. 互联网必备技能1-写好PPT
  17. android+ue设计原则,【岗位课】移动端UI/UE设计湿
  18. 创业公司如何做好信息安全(下)
  19. 艾司博讯:拼多多子账户的操作流程
  20. 在破败中崛起,在寂灭中复苏。   沧海成尘,雷电枯竭,那一缕幽雾又一次临近大地,世间的枷锁被打开了,一个全新的世界就此揭开神秘的一角……

热门文章

  1. iOS 9.0以后支持http协议
  2. JavaScript中对象成员的可见性
  3. (收藏)Turbo C 2.0、Borland C++库函数及用例
  4. [网络安全提高篇] 一〇四.网络渗透靶场Oracle+phpStudy本地搭建万字详解(SQL注入、XSS攻击、文件上传漏洞)
  5. 【数据结构与算法】之深入解析“分数到小数”的求解思路与算法示例
  6. Swift之缓存文件处理
  7. 2015年第六届蓝桥杯 - 省赛 - C/C++大学A组 - H. 饮料换购
  8. Go 语言切片(Slice)
  9. 【机器视觉】 dev_update_var算子
  10. 【Tools】VNC Server 6.7安装详解