聚合类和字面值常量类

聚合类

聚合类使得用户可以直接访问其成员,并且具有特殊的初始化语法形式。当一个类满足如下条件时,我们说它是聚合的:

  • 所有成员都是public的
  • 没有定义任何构造函数
  • 没有类内初始化
  • 没有基类,也没用virtual函数。

下面的类都是一个聚合类

struct Data 

{

  int ival;

  string s;

};

我们可以提供一个花括号括起来的成员初始化列表,并用它初始化聚合类的数据成员:

//val1.ival=0;val1.s=string("Anna")

Data val1={"Anna",1024"};

初始值的顺序必须与声明的顺序一致,也就是说,第一个成员的初始值要放在第一个,然后是第二个,以此类。下面的例子是错误的:

//错误:不是使用"Anna"初始化ival,也不能使用1024初始化s

Data val2={"Anna",1024};

与初始化数组元素的规则一样,如果初始值列表中的元素个数少于类的成员数量,则靠后的成员被值初始化。初始值列表的元素个数绝对不能超过类的成员数量。

值得注意的是,显示地初始化类的对象的成员存在三个明显的缺点:

  • 要求类的所有成员都是public的
  • 将正确初始化每个对象的每个成员的重任交给了类的用户(而非类的作者)。因为用户很容易忘掉某个初始值,或者提供一个不恰当的初始值,所以这样的初始化过程冗长乏味而且容易出错。
  • 添加或删除一个成员之后,所有的初始化语句都需要更新。

 

字面值常量类

我们提到过constexpr函数的参数和返回值必须是字面值类型,除了算术类型、引用和指针外,某些类也是字面值类型。和其他类不同,字面值类型的类可能含有constexpr函数成员。这样的成员必须符合constexpr函数的所有要求,它们是隐式const的。

数据成员都是字面值类型的聚合类是字面值常量类。如果一个类不是聚合类,但它符合下述要求,则它也是一个字面值常量类:

  • 数据成员都必须是字面值类型。
  • 类必须至少含有一个constexpr构造函数
  • 如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式;或者如果成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数。
  • 类必须使用析构函数的默认定义,该成员负责销毁类的对象。

 

constexpr构造函数

尽管构造函数不能是const的,但是字面值常量类的构造函数可以是constexpr函数。事实上,一个字面值常量类必须至少提供一个constexpr构造函数。

constexpr构造函数可以声明成=default的形式(或者删除函数的形式)。否则,constexpr构造函数就必须既符合构造函数的要求(意味着不能包含返回语句),又符合constexpr函数的要求(意味着它能拥有的唯一可执行语句就是返回语句)。综合这两点可知,constexpr构造函数体一般来说应该是空的。我们通过前置关键字constexpr就可以声明一个constexpr构造函数了:

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) {hw=b;}
private:
    bool hw;
    bool io;
    bool other;
};

constexpr构造函数必须初始化所有数据成员,初始值或者使用constexpr构造函数,或者是一条常量表达式。

constexpr构造函数用于生成constexpr对象以及constexpr函数的参数或返回类型:

constexpr Debug io_sub(false,true,false);  //调试IO

if(io_sub.any())  //等价于if(true)

  cerr<<"print appropriate error messages"<<endl;  

constexpr Debug prod(false);  //无调试

if(prod.any())  //等价于if(false)

  cerr<<"print an error message"<<endl;

 

时间: 2024-11-09 16:40:48

聚合类和字面值常量类的相关文章

为什么类中的常量没有同步过来

集测的时候出现原来的功能不好使的情况(把我急死了); 手机号换绑(接口C)后,查询个人信息(接口I),显示的信息还是老的手机号. 后来看日志,发现接口C 和接口I 调用的ip不同,但是两个接口引用的是同一个常量啊? 我就突然想到了修改常量类之后,接口C 没有重新编译的问题. 为了确认这点,我找运维,请他把这两个接口的service  class文件发给我,我使用jd-gui.exe 反编译,发现这两个接口中的ip确实不同.于是我决定找到问题的源头,我详细问了运维部署项目的流程.集测部署流程如下:

cobertura-maven-plugin 生成单元测试报告时排除接口,异常类,常量类

当我们为一个项目用cobertura生成单元测试覆盖率报告时,常常有以下需求: 需求说明: 因为一个项目有许多接口定义,常量定义,异常类定义,这些类是不需要单元测试的.而当我们用cobertura来生成测试报告时候,如果不排除这些类的话,就会使得报告的数据不太好看,因为毕竟有某些被算进去的类没有对应的单元测试嘛.所以我们就希望可以在用cobertura-maven-plugin生成测试报告时候,能自动排除这些接口,常量,异常类. 解决方法: 其实很简单,只要在项目的pom.xml中用到cober

如果常量类进行改变时,只编译常量类,而使用常量的类不重新编码,这样改动实际上算没有生效(转)

  在Java开发过程中有很多通用的准则,遵守这些准则能够避免很多不必要的错误发生,让代码的质量更高,下面的内容为书籍第一章<Java开发中通用的方法和准则>的阅读笔记. 一.不要在常量和变量中出现易混淆的字母 例如数字1和小写字母l容易混淆,数字0和字母o容易混淆,因此在变量或常量命名时需要避免两个同时出现. 另外命名最好遵守Java编码规范:包名全小写,类名首字母全大写,常量全部大写并用下划线分隔,变量采用驼峰命名法等等. 二.不要让常量蜕变成变量 常量应该保证在编译期就确定其值不变,而不

《Android 应用案例开发大全(第二版)》——2.8节工具常量类

2.8 工具常量类Android 应用案例开发大全(第二版)上一节完成了线程相关类的详细介绍,这一节将对本案例工具类Vector3f的开发进行介绍,Vector3f是一个向量类,在该类里进行了向量的基本运算,如向量的加法.减法.求模等,具体代码如下所示. 1 package com.bn.ld.Vectors; 2 public class Vector3f { 3 public float x; // 向量中的_x_ 4 public float y; // 向量中的_y_ 5 public

java中什么是实体类,为什么实体类的变量都用private修饰?

问题描述 java中什么是实体类,为什么实体类的变量都用private修饰? java中什么是实体类,为什么实体类的变量都用private修饰?能否举个实体类的简单例子,谢谢 解决方案 关于什么是实体类,可以看这里:Java什么是实体类实体类有什么用? 例如一个订单实体类Order.java,里边:id(主键).orderNo(订单号).userId(订单所属用户ID).status(支付状态).createTime(创建时间)等属性. 因为这些属性,基本都是供订单类自己使用的,所以一般都将它们

php函数、类和对象以及类的封装、继承、类的静态方法、静态属性

原文:php函数.类和对象以及类的封装.继承.类的静态方法.静态属性 1.函数     php内置函数可以直接使用,如果没有安装php扩展即可     自定义函数 //函数function 函数名 function dump($var = null){ //支出默认参数值 echo '<pre/>'; var_dump($var); } 2.类(class)和对象( new Obj) <?php //定义一个人的类,现在还不是对象 class Person { //私有属性 privat

关于java,类的定义以及类之间的关系

问题描述 关于java,类的定义以及类之间的关系 一个公司需要开发一个能够计算雷达屏幕上两点之间距离的应用程序,将它用于空中交通控制应用的一部分 解决方案 在java中类和类之间的关系基本上有依赖.关联.聚合.组合等 一.继承关系 继承指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功能的能力.在Java中继承关系通过关键字extends明确标识,在设计时一般没有争议性.在UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子

JAVA的可变类与不可变类

1.可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容. 不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容.不可变类的实例一但创建,其内在成员变量的值就不能被修改. 2.如何创建一个自己的不可变类: .所有成员都是private .不提供对成员的改变方法,例如:setXXXX .确保所有的方法不会被重载.手段有两种:使用final Class(强不可变类),或者将所有类方

Swift游戏实战-跑酷熊猫 06 创建平台类以及平台工厂类

原文:Swift游戏实战-跑酷熊猫 06 创建平台类以及平台工厂类   这节内容我们一起学习下随机长度的踩踏平台的原理是怎么样的. 要点: 平台类 我们的平台类继承于SKNode,这样就能被添加进其它节点进而显示在场景中. 它有一个方法来创建平台,这个方法接收一个包含SKSpriteNode的数组.将数组里面的对象横向拼接在一起组成一个完整的平台.同时计算出平台的宽度 onCreate(arrSprite:[SKSpriteNode]){ for platform in arrSprite{ p