一般来说,关于C++类静态成员的初始化,并不会让人感到难以理解,但是提到C++ 静态成员的"类内初始化"那就容易迷糊了。

我们来看如下代码:

 //example.h
#include<iostream>
#include<vector>
using namespace std; class Example{
public:
static double rate = 6.5;
static const int vecSize = ;
static vector<double> vec(vecSize);
}; //example.cpp
#include "example.h"
double Example::rate;
vector<double> Example::vec;

我们需要判断上面的静态数据成员的声明和定义有没有错误,并解释原因。

首先,要谨记:通常情况下,不应该在类内部初始化成员,无论是否为静态成员。

其次,若一定要在类内初始化静态成员,那么就必须满足如下条件才行:

1) 静态成员必须为字面值常量类型的constexpr。

所谓的字面值类型就是通常遇到的:算术类型,引用,指针等。字面值常量类型就是const型的算术类型,引用,指针等。

所谓的constexpr,就是常量表达式,指值不会改变在编译过程中就能得到计算结果的表达式。比如字面值,或者用常量表达式初始化的const对象也是常量表达式。为了帮助用户检查自己声明/定义的变量的值是否为一个常量表达式,C++11新规定,允许将变量声明为constexpr类型,以便由编译器来进行验证变量是否为常量表达式。

2)给静态成员提供的初始值,必须为常量表达式

注意:在C++ primer 第五版中说:只能给静态成员提供const 整数类型的类内初始值,且该const整数类型的初始值必须是常量表达式。我觉得是有误的!详情见后面分析。

有了这两条原则,我们就可以对上面的代码进行验证了。

1)static double rate = 6.5;

显然不满足第一条:因为rate不是常量类型。改成constexprt static const double rate = 6.5即可

从这里也可以看出初始值不一定必须为const 整数类型。

ps: 如果我们不再这里加入constexprt修饰符的话,编译器会提示错误:error: ‘constexpr’ needed for in-class initialization of static data member ‘const double Example::rate’ of non-integral type [-fpermissive]
大体意思就是,对于非const整数类型的初始值,如果它是常量表达式的话,我们需要手工在前面添加修饰符constexprt。

至于Example.cpp文件中的定义部分,由于我们已经在类内部进行了初始化,就不需要再在类外部进行定义了。如果非要定义的话,必须采用如下格式:

//example.cpp

constexpr const double Example::rate;  //其中的const是可以删除的,因为constexprt本身就包含了const

2)static const int vecSize = 20;

vecSize是const int类型的,且为常量表达式——满足第一条;提供的初始值为20,是一个常量表达式——满足第二条!且由于是const int型的,前面可以不用修饰符constexpr。

3)static vector<double> vec(vecSize);

错误!vector是模板不是字面值常量类型,所以不满足第一条。应该改为 static vector<double> vec; //仅仅且只能进行声明,不能定义

然后在Example.cpp中进行定义:

static vector<double> vec(Example::vecSize);

现在我们可以在Example.cpp中添加测试代码进行测试了:

 #include "example.h"
vector<double> Example::vec(Example::vecSize);
constexpr const double Example::rate; int main(){ Example::vec.push_back(10.5);
cout << Example::vec.back() << endl;
cout << Example::rate << endl;
cout << Example::vecSize << endl;
}

执行结果:

wanchouchou@wanchouchou-virtual-machine:~/c++/7.5$ ./Example
10.5
6.5

C++ 静态成员的类内初始化的更多相关文章

  1. 错误: ISO C++ 不同意在类内初始化很量静态成员

    错误: ISO C++ 不同意在类内初始化很量静态成员      今天開始学C++ primer,在牵扯到Sales_item.h头文件时.出现了一些问题(和C++11新特性相关),当前的编译器版本号 ...

  2. 【转】forbids in-class initialization of non-const static member不能在类内初始化非const static成员

    转自:forbids in-class initialization of non-const static member不能在类内初始化非const static成员 今天写程序,出现一个新错误,好 ...

  3. C++11 类内初始化

    C++11新标准规定,可以为数据成员提供一个类内初始值.创建对象时,类内初始值将用于初始化数据成员.没有初始值的成员将默认初始化. 对类内初始值的限制与之前介绍的类似:或者放在花括号里,或者放在等号右 ...

  4. 为什么static成员必须在类外初始化,而不能在类的头文件中初始化

    为什么static成员必须在类外初始化 为什么静态成员不能在类内初始化 在C++中,类的静态成员(static member)必须在类内声明,在类外初始化,像下面这样.   class A { pri ...

  5. C++builder XE10 终于支持类内变量初始化了

    Win32终于支持类内变量初始化了,C++11 用bcc32C编译器  llvm CLang.还支持Unicode 中文汉字 变量名. 用经典的bcc32编译还是不支持! class TPerson ...

  6. 类内const static(static const)成员变量初始化问题

    在查找const相关资料的过程中,又遇到了另外一个问题,就是C++类中const static(或者static const)成员变量应当如何初始化的问题. 查阅了许多资料,发现VC环境下,只允许co ...

  7. c++ 类内static成员初始化

    类内部的static成员,除了为const static 且为整数类型(int char bool)可在类内部初始化. 其他的都建议在对应的cpp文件中进行初始化. test.h #ifndef TE ...

  8. java类的初始化顺序

    在java中,当我们new一个对象时,对象中的成员,初始化块以及构造方法的加载是有一定的顺序的,看下面一副图: 一.单类(无基类)下的初始化顺序: public class Parent { stat ...

  9. java类的初始化和对象的创建顺序

    学习java编程思想--类的初始化p146 类的加载顺序* 1加载器启动找到 xxx.class文件,通过extends关键字寻找基类,先加载基类* 2类初始化先初始化static成员变量和stati ...

随机推荐

  1. axios获取后端数据

    axios向后端请求数据时,一直获取不到数据, 后来改成这样写获取到了数据 不是一个this,有人说用箭头函数就可以了.

  2. quartz调度

    http://www.cnblogs.com/lzrabbit/archive/2012/04/14/2446942.html

  3. PHP数据库扩展 - PDO操作

    PDO操作 PDO操作 描述:odp是php对数据库操作统一化的操作 语法:$pdo = new PDO("DB名:host=主机名;dbname=DB名","DB账号& ...

  4. Java堆内存又溢出了!教你一招必杀技

    JAVA堆内存管理是影响性能主要因素之一.堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的. 先看下JAVA堆内存是如何划分的,如图: JVM内存划分为 ...

  5. Python中列表的深浅拷贝

    copy_lst = [ ('py对象三要素',), ('== 比较运算符',), ('is 身份运算符',), ('小数据池',), ('列表的浅拷贝',), ('列表的深拷贝',), ] py对象 ...

  6. 20181225 基于TCP/IP和基于UDP/IP的套接字编程

    一.TCP/IP的套接字编程 服务器端代码: import  socket​server = socket.socket() # 默认是基于TCP# 基于TCP的对象serve=socket.sock ...

  7. P1880 [NOI1995]石子合并【区间DP】

    题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...

  8. loj2061 「HAOI2016」放棋子

    答案就是错排数 n = int(input()) f = [0] * 205 f[0] = 1 for i in range(2, n+1): f[i] = (i-1) * (f[i-1] + f[i ...

  9. 微服务化的不同阶段 Kubernetes 的不同玩法

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 作为容器集群管理技术竞争的大赢家,Kubernetes已经和微服务紧密联系,采用Kubernetes的企业往往都开始了微服务架构的探索.然而不同企业 ...

  10. hnust 可口可乐大促销

    问题 B: 可口可乐大促销 时间限制: 1 Sec  内存限制: 128 MB提交: 653  解决: 323[提交][状态][讨论版] 题目描述 最近可口可乐在搞大促销活动,1瓶可乐只要1元钱.而且 ...