聚合类和字面值常量类

聚合类

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

  • 所有成员都是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;

聚合类和字面值常量类,布布扣,bubuko.com

时间: 2024-10-05 11:36:26

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

c++学习笔记——字面值常量类

字面值常量类:数据成员都是字面值类型的聚合类是字面值常量类.如果一个类不是聚合类,但是它符合一下要求,则它也是个字面值常量类: 1.数据成员都必须是字面值类型. 2.类必须至少含有一个constexpr构造函数. 3.如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式:或者如果成员属于某种类型,则初始值必须使用成员自己的 constexpr构造函数. constexpr构造函数: 1.尽管构造函数不能是const的,但是字面值常量类的构造函数可以是constexpr函数.

静态修饰符static,类中的常量定义修饰符

static可以用来区分成员变量.方法是属于类本身还是属于类实例化后的对象.有static修饰的成员属于类本身,没有static修饰的成员属于类的实例. 静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失static是一个修饰符,用于修饰成员(成员变量和成员函数)静态成员随着类的加载而加载.静态成员优先于对象存在.静态成员被所有对象所共享静态成员多了一个中调用方式,可以被类名直接调用.静态的优缺点优点: 静态成员多了一种调用方式.可以直接被类名调用 格式 :类名.静态成员.也

php类和对象: 类常量

类常量 定义在类中的常量称为类常量.类常量与类本身及特定实例无关,可以在类外部任何位置引用.PHP中使用关键字 const 来修饰类常量.类常量通常要大写,如果类常量由多个单词组成,建议使用下划线分隔.语法格式如下: 类名称::类常量名称 类常量的用法与类静态属性和静态方法很相似,同样,如果想在同一类的成员方法中访问类常量,可以通过在该类常量的名称前加上操作符”self::”来实现.

只能通过类而不能通过类的实例访问常量属性

1.静态属性.静态方法 在面向对象编程中,我们不仅可以通过对象访问方法和属性,还可以通过类来访问它们.这样的方法和属性就是“静态的”(static),必须用static关键字来声明. [php] view plaincopyprint? class staticExample { staticpublic $num = 0; staticpublic function sayNum() { echoself::num; } } 静态方法是以类作为作用域的函数.静态方法不能访问这个类中的普通属性,

C++类中定义常量的方法

好久没用过C++,本来就不太熟悉,今天突然写到一个类,需要在类中定义一个常量,居然花了很长时间. 刚开始写了static const int num = 100: 这样是不行的,因为常量只能在初始化列表中初始化,如果去掉const的话,又不能有"常量"的效果, 在类外用宏定义看起来不科学,类外const也一样,后面就大概搜索了一下,可以选择用枚举类型来替代达到 差不多的效果.具体的代码看下面: class User{ public: enum { MaxNum = 20}; } 写下来

php--在类中声明常量的关键字

Final.static.const.instanceod Final :final关键字可以加在类或者类中方法之前,但是不能使用final标识成员属性. 作用: 使用final标识的类,不能被继承. 在类中使用final标识的成员方法,在子类中不能覆盖. const:const关键字是在类中定义常量,而define()函数也是定义常量,但它是在类外定义常量. 调用方式和静态成员是一样的,都是通过类名或者在成员方法中使用self关键字进行访问,但是不建议使用对象引用进行访问. instanceo

利用Java注解将常量类生成js文件供前端调用

注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事.标记可以加在包,类,字段,方法,方法的参数以及局部变量上. 1)定义一个最简单的注解 public @interface MyAnnotation {     //...... } 2)把注解加在某个类上: @MyAnnotation public class AnnotationTes

开发技巧----------项目中常量类的定义方式

问题: 有开发经验的同学都知道,常量类是一个最常用的定义数据字典的方式.但是随着项目的开发时间和开发团队的变化经常会出现2中特别苦逼的情况.第一种情况是项目中到处都能看到各种各样的常量类:第二种情况是一个常量类里定义非常多的常量,甚至有的超过100了.这两种情况的缺点估计大家都非常的清楚,第一种代码离散.冗余.维护难:第二种也是维护难,更痛苦的时候用ide的时候很难找到自己需要的常量. 解决办法: 1.使用静态内部类对常量进行分组(可以多级分组,但是建议最多3级) 2.外部文件(这里不讨论) 3

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

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