C++ 类的静态成员 类内初始化
目录
问题分析
问题:C++ primer 5e中文版 练习7.58
推荐阅读:https://www.jianshu.com/p/09b204be66af
正如这个博主所提到的,在C++ primer中的翻译不太容易理解,英文原版中的意思应该是:
可以为const 整数类型的静态成员提供类内初始值(当然也可以在类外定义)
必须为constexpr的静态成员提供类内初始值(必须在类内定义)
![](https://img-blog.csdnimg.cn/20210819140801842.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21hZ2ljX3Nob3dfdGltZQ==,size_16,color_FFFFFF,t_70)
代码分析
下面将通过几段代码来学习这个部分:
非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是一种标准库类型,它是否属于字面值类型?是否要根据对象来判断?