C++ 类的静态成员 类内初始化

目录

问题分析

 代码分析

非const(以double为例,同样适用于int等整型)

const类型

const非整型

const整型

constexpr类型(以double举例,整型变量同)

总结

补充



问题分析

问题:C++ primer 5e中文版 练习7.58

推荐阅读:https://www.jianshu.com/p/09b204be66af

正如这个博主所提到的,在C++ primer中的翻译不太容易理解,英文原版中的意思应该是:

可以为const 整数类型的静态成员提供类内初始值(当然也可以在类外定义)

必须为constexpr的静态成员提供类内初始值(必须在类内定义)

【引用】 https://www.jianshu.com/p/09b204be66af


 代码分析

下面将通过几段代码来学习这个部分:

非const(以double为例,同样适用于int等整型)

代码段1:

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate(){ return test1; }
  static double test1;
};

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

 分析1:

报错内容:undefined reference to `Account::test1'

class中的static double test1只是一个声明,而未定义

代码段2:(在代码段1的基础上尝试类内定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate(){ return test1; }
  static double test1 = 3.14;
};

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

 分析2:

报错:error: 'constexpr' needed for in-class initialization of static data member 'double Account::test1' of non-integral type [-fpermissive]|

大致意思就是double类型而非integral类型,

不能在类内定义

代码段3:(尝试在类外定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate(){ return test1; }
  static double test1;
};

double Account::test1 = 3.14;

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析3:

正确,注意test1的定义方式


const类型

const非整型

代码段1:

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate(){ return test1; }
  static const double test1 = 3.14;
};

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析1:

error: 'constexpr' needed for in-class initialization of static data member 'const double Account::test1' of non-integral type [-fpermissive]

大致意思就是const double类型而非integral类型,不能在类内定义

代码段2:(类外定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate(){ return test1; }
  static const double test1 ;
};

const double Account::test1 = 3.14;

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析2:

正确


const整型

代码段1:(类内定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  int rate(){ return test1; }
  static const int test1  = 3;
};

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析1:

正确

代码段2:(类外定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  int rate(){ return test1; }
  static const int test1;
};

const int Account::test1 = 3;
int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析2:

正确


constexpr类型(以double举例,整型变量同)

代码段1:(尝试类外定义)

//代码已做必要精简
#include <iostream>
class Account {
public:
  int rate(){ return test1; }
  static constexpr int test1;
};

const int Account::test1 = 3;

int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析1:

error: 'constexpr' static data member 'test1' must have an initializer

constexpr类型必须有类内初始值

代码段2:(类内初始化)

//代码已做必要精简
#include <iostream>
class Account {
public:
  int rate(){ return test1; }
  static constexpr int test1 = 3;
};


int main()
{
  Account ac1;
  std::cout<<ac1.rate()<<std::endl;
  return 0;
}

分析2:

正确


总结

  • 非const类型,必须类内声明,类外定义(适用于整型和浮点型)
  • const类型中的整型,在类内声明,其定义位置可以在类外或类内
  • const类型中的浮点型,在类内声明,类外定义
  • constexpr类型,必须在类内声明,类内定义(适用于整形和浮点型)

“即使一个常量静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员”

----C++ primer 5e中文版 P271

完整代码测试:

//代码已做必要精简
#include <iostream>
class Account {
public:
  double rate()
  {
    std::cout<<test1<<std::endl;
    std::cout<<test2<<std::endl;
    std::cout<<test3<<std::endl;
    std::cout<<test4<<std::endl;
    std::cout<<test5<<std::endl;
    std::cout<<test6<<std::endl;
    return test1;
  }
  //非const
  static double test1;
  static int test2;

  //const
  static const double test3;
  static const int test4;
  //static const int test4 = 3;

  //constexpr
  static constexpr double test5 = 3.14;
  static constexpr int test6 = 3;


};

double Account::test1 = 3.14;
int Account::test2 = 3;

const double Account::test3 = 3.14;
const int Account::test4 = 3;

int main()
{
  Account ac1;
  ac1.rate();
  //Account *ac2 = &ac1;
  //ac2->rate();
  return 0;
}

补充

"字面值类型包括算数类型(整型、浮点型)、引用、指针、字面值常量类、枚举,而自定义类Sales_item、IO库、string类型则不属于字面值类型。“                

                                                                                 ----C++ primer 5e中文版P59、267、736

vector是一种标准库类型,它是否属于字面值类型?是否要根据对象来判断?

posted @ 2021-08-19 14:52  Keep_Silent  阅读(76)  评论(0编辑  收藏  举报