建设银行手机登陆网站,网站建设插件代码大全,网站上怎么做返回主页链接,网络公司经营范围写电子商务tags: C OOP
引子: 类为什么需要静态成员
有时候类需要与它的一些成员与类本身直接相关, 而不是与类的各个对象都保持关联, 这就减少了成员与每一个类的实例对象的联系, 从而降低资源占用. 另一方面, 如果每次都需要重新更新该成员, 使得对象使用新的值, 这时候只需要修改一份…
tags: C OOP
引子: 类为什么需要静态成员
有时候类需要与它的一些成员与类本身直接相关, 而不是与类的各个对象都保持关联, 这就减少了成员与每一个类的实例对象的联系, 从而降低资源占用. 另一方面, 如果每次都需要重新更新该成员, 使得对象使用新的值, 这时候只需要修改一份该成员.
声明静态成员
要点 在成员声明之前加上关键字static使得其与类关联在一起 静态成员可以是public或private的, 类型可以是常量, 引用, 指针, 类等 类的静态成员存在于任何对象之外, 对象中不包含任何与静态数据成员有关的数据(这也是为什么需要类内声明, 类外初始化的原因) 类的静态成员函数也不与任何实例对象绑定在一起, 不包含this指针. 类的静态成员函数不能声明为const的, 也不能在static函数体内使用this指针. 正因为没有this指针, 所以不能加cv-修饰符 error: static member function static void P::f() cannot have cv-qualifier当将const限定符应用于非静态成员函数时它会影响this指针。对于类C的const限定成员函数this指针的类型为C const*而对于非const限定的成员函数this指针的类型为C*。静态成员函数没有this指针(此类函数不会在类的特定实例上调用)因此静态成员函数的const限定没有任何意义。 在类外可以直接通过作用域运算符直接访问静态成员, 即使直接通过类名访问, 也不会出错. 成员函数可以不通过作用域运算符直接使用静态变量; 在类的外部定义静态成员时, 不能重复使用static关键字, 该关键字只能出现在类内部的声明语句中. 因为静态数据成员不属于类的任何一个对象, 所以它们并不是在创建类的对象时被定义的. 这意外着它们不是由类的构造函数初始化的. 一般来说, 不能在类的内部初始化静态成员, 而必须在类的外部定义和初始化每一个静态成员. 经过测试, 静态常量数据成员可以在类内初始化, 静态成员函数可以在类内定义. 一个静态数据成员只能定义一次. 类似于全局变量, 静态数据成员定义在任何函数之外, 所以静态数据成员一旦被定义, 就将一直存在于程序的整个生命周期中. 可以为静态成员提供const整数类型的类内初始值, 不过要求静态成员必须是字面值常量类型的constexpr. 初始值必须是常量表达式, 因为这些成员本身就是常量表达式, 所以能用在所有适合于常量表达式的地方. 如果某个静态成员的应用场景仅限于编译器可替换其值的情况, 则一个初始化的const或者constexpr static不需要分别定义; 反之, 如果将其用于值不能替换的情况, 则该静态成员必须有一条定义语句. 例子: 如果某一成员的作用就是定义类内另一成员的size, 就不需要专门在类外定义该静态常量了. // 在类内
static constexpr int size 10;
double array[size];如果在类内提供了一个初始值, 则成员的定义不能再指定一个初始值了. 例子: // 当需要把下面的值传给一个接受const int的函数时, 必须定义size
static constexpr int P::size 10;
void test(const int a) { cout a endl; }
void t2() { test(P::MAX_length); }即使一个常量静态成员在类内被初始化了, 通常情况下也应该在类外部定义(我认为应该翻译为生命)一下该成员. // 类内: static constexpr int MAX_length 10;
// 类外:
constexpr int P::MAX_length;参考: Definitions and ODR (One Definition Rule) - cppreference.com;c - In-class initialization of static data members - Stack Overflow;★\bigstar★c - Static data member initialization in the class definition? - Stack Overflow 有点奇怪.
例子: 访问静态成员 注释掉的就是错误的用法. #include iostream
using namespace std;
class P {
public:P() default;~P() default;/* static void f()const{} */static void g() {/* this-MAX_age 1; */cout g()\n;}static void h();static const int MAX_age 1;static constexpr int MAX_length 1;/* static int MAX_account 1; */static int MAX_account;
};
int P::MAX_account 10;
/* static void P::h() { cout h()\n; } */
void P::h() { cout h()\n; }void t1() {int b P::MAX_age;cout b endl;P::MAX_account 12;cout P::MAX_account endl; // 12
}int main(int argc, char *argv[]) {t1();return 0;
}与非静态成员的区别
要点 静态成员可以是不完全类型(可以不是指针或引用, 但是非静态成员不行) 不完全类型: class P; // 前向声明在声明之后, 定义之前, P是不完全类型. 即: 只知道P是一个类类型, 但是不清楚到底包含哪些成员. 静态成员可以作为默认实参. 非静态数据成员不能作为默认实参, 因为其值属于对象的一部分, 如果作为默认实参, 将无法真正提供一个对象以便从中获取成员的值, 导致错误.