欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > c/c++ >内容正文

c/c++

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

发布时间:2024/4/18 c/c++ 52 豆豆
生活随笔 收集整理的这篇文章主要介绍了 C++Primer:字面值常量类调用函数错误(p268书中示例报错) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

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. 基础相关知识(可跳过)

  • 常量表达式。值不会改变并且在编译过程就能得到计算结果的表达式。
  •  

    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()结果未知
  • 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本身也是常量
  • 字面值类型。算术类型、引用和指针属于字面值类型,自定义类、IO库、string类型不属于字面值类型。只有字面值类型才能声明constexpr。

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

  •  

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

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

  • 3. 分析

  • 由示例可知,io_sub和prod是constexpr变量。故io_sub和prod本身便是常量,其类型相当于const Debug
  •  

    //constexpr Debug等价于 const Debug constexpr Debug io_sub(false, true, false); constexpr Debug prod(false);
  • 成员函数any()是一个constexpr函数。在c++11标准下,constexpr函数是常量成员函数,在c++14标准下,constexpr函数不是常量成员函数。我的编译器默认constexpr函数不是常量成员函数。
  •  

    constexpr bool any() //c++11标准下等价于 bool any () const //c++14标准下等价于 bool any()
  • 常量对象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()修改为常量成员函数:

  • 在any()后加const使其成为常量成员函数。
  •  

    constexpr bool any() const {return hw | io | other; }

    运行结果

  • 编译时使用c++11标准,是使constexpr函数默认是常量成员函数。
  • 运行结果

    5. 总结

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


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

    总结

    以上是生活随笔为你收集整理的C++Primer:字面值常量类调用函数错误(p268书中示例报错)的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。