跳转至

static

全局的静态内联函数

静态方法 不属于任何对象

//.h头文件文件定义
//保留两位小数
static inline NSDecimalNumberHandler *decimalNumberHandler2(void) {
    return [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
}

函数内部的变量

普通的变量

调用的时候在堆栈上分配内存,函数调用结束之后变量就没了。

下次再调用的时候,会重新生成新的变量。

静态的变量

使用static定义变量

不是在堆栈上,在静态数据区。第一次的时候分配变量内存,调用结束后,静态数据区变量没有撤销,一直保存,每次调用函数,用的都是之前的变量数据。静态数据区一直等程序停止才会消失。

函数内部的静态变量,不能在其它函数里调用,作用域只在自己函数内部。

只是生命期延长了,用的值是同一个变量。

如果不用函数内部的静态变量,则需要使用全局变量。

尽可能的不要使用全局变量,使用静态变量是一个非常好的设计方法。

例:

#include <iostream>

using namespace std;

char *a = "abcdefghijklmnopqrstuvwxyz";

char oneChar(const char *charArray) {
      //static 只执行一次, 赋一次值。 以后都是同一个s。
    static const char *s = charArray;
    if (*s == '\0') {
        return 0;
    }
    return *s++;
}

//运行结果会把每一个字符输出。
void test() {
    char c;
    while ((c = oneChar(a)) != 0) {
        cout << c << endl;
    }
}

静态数据成员和静态成员函数

静态数据成员

存钱银行会给利息,每一个人的利率都是一样的,不需要给每个人一个利率。改变利率也不方便。

利率做成全局变量也可以,但是不太好。因为只有账号的类需要使用,其它的类不需要使用。

所以写在类里面,做成静态的。这就叫静态数据成员。C++会把它保存在单独的数据区里。

//银行账号
class Account {
public:
    Account(std::string name, double money);
    double getAmount() const;//获取Amount
    void deposit(double money);//存钱
private://私有成员变量
    std::string owner;//姓名
    double amount;      //金额
    static double interestRate;//利率。这只是一个声明,没有分配内存
};

interestRate在.h文件中只是声明,没有分配内存。不能初始化。

还需要在.cpp中定义。并且还可以初始化。static不需要写。在这时分配内存。

静态成员函数只能访问静态数据成员,只能调用静态成员函数

要想修改静态的成员函数(利率),定义的函数也得是静态的。只有静态成员函数才能访问静态数据成员。

修改静态数据成员的函数写成静态的。

静态的成员函数,用类去调用,而不是某一个对象。

静态的函数只能使用静态的数据成员和函数,不能使用非静态的成员,也不能调用非静态的成员函数。

非静态成员函数可以访问静态的成员函数。也可以调用静态的数据成员。

静态的数据成员属于类,不属于任何对象,所以不能够使用this->

非静态的成员函数才可以用this->

静态成员函数和静态数据成员是对全局函数全局变量的改进。

静态数据成员的存储定义和初始化

非静态成员也叫实例成员,静态成员也叫类成员,是所有的类的对象共享的。

class Person
{
  //每个person对象都有一个自己的m
  int m;
  //所有的person共用一个n
  static int n;     //这只是一个声明,
}

int Person::n;  //  定义这个静态成员,分配内存。如果没有这一行,后面使用n 改变n的值不会起作用,因为没有分配内存。

非静态的成员,在创建对象的时候分配内存。

静态的成员,因为它不属于对象,所以创建对象的时候并不会分配内存。需要再写一行定义,分配内存。

静态的成员是和类关联在一起。

构造函数后面加一个冒号:初始化列表。非静态的可以在构造函数初始化列表初始化,但是不能初始化静态成员,因为静态的成员不属于一个对象,

静态成员不是一个对象的组成部分。

对静态成员初始化是直接分配内存的时候初始化:

int Person::n = 200;

在类的外面定义 分配内存 初始化。在类里声明。

嵌套类和局部类的静态成员

例外:

静态的常量的整型 可以在类里面初始化。

这个例外仅仅是针对静态的常态的整型。数组 double都不行。

#include <iostream>
using namespace std;

//静态成员也可以是自定义的类型。一个自己写的类class。
class X {
    int i;
public:
    X(int ii):i(ii){}
};

class Person {
public:
    int m;
    static const int k = 99;
    static const long l = 12345;
    static const double d;
    static const int scIns[];

    static int n;//这只是一个声明

    static X x;
    static const X x2;
    static const X x3[];

    Person();

    //嵌套类
    class Inner {
        static int i;
    };
};

//定义 分配内存
int Person::Inner::i = 55;
int Person::n = 500;//定义静态常量,分配内存
const double d = 1.2;
const int scIns[] = {1,2,3,4,5};

X Person::x(8);
const X Person::x2(9);
const X Person::x3[] = {X(1), X(2), X(3), X(4)};

局部类:

在一个函数的内部定义一个类

在复杂的数据结构中,嵌套类是可以定义静态成员的,局部类不可以定义静态成员。

主要:

声明和定义

静态成员函数

#include <iostream>
using namespace std;
class Test {
    int i;
    static int j;
public:
    //类里面有静态成员函数
    static void f();//静态
    static void f2(){}

    void g(){}//非静态
};

int Test::j;
void Test::f() {
    cout << "Test::f()" << endl;
}

可以通过对象来调用f。还可以通过类调用f,不需要创建对象。

静态的成员函数相当于是对象共用的全局函数,和类关联在一起的,通过类调用。

静态的数据成员,在源文件中要写上定义:

也可以进行初始化

  • 静态的函数

可以对静态成员操作,不可以对非静态成员操作。可以调用静态函数,不可以调用非静态的。

静态的是所有对象共用的,属于类。

静态成员 静态函数:相当于全局函数。全局变量。但并不一样,是在类里的。

静态成员静态函数替代全局成员全局函数。这样写比较好。

  • 非静态函数:

可以对非静态的变量操作,也可以对静态的操作。可以操作自己的,可以操作共用的。

可以调用普通非静态函数,也可以调用静态的函数。

静态对象

  • 函数内部的静态对象
  • 静态对象的析构函数
  • 全局静态对象

静态对象和普通的静态变量是一样的,普通的静态变量是C++内置的类型,静态对象是我们自己写的类型。

class X {
    int i;
public:
    X(int ii = 0) : i(ii){}
    ~X() { cout << "X::~X()" << endl; }
};

void f()
{
    static int i;
    static X x(47);
    static X x2;
    cout << "i = " << i << endl;
}

静态变量,C++会自动的初始化,i默认值是0。x会调用X类的无参数的构造函数,或者是有参数并且参数有默认值的构造函数(有参数没有默认值的话会报错)。

因为是静态的,只有整个程序运行结束之后,才会调用析构函数。

class Obj {
    char c;
public:
    Obj(char cc) : c(cc)
    {
        cout << "Obj::Obj() for" << c << endl;
    }
    ~Obj()
    {
        cout << "Obj::~Obj() for" << c << endl;
    }
};

Obj a('a');

void f()
{
    static Obj b('b');
}

void g()
{
    static Obj c('c');
}

a是全局的对象,b和c是函数内部的 静态对象,全局对象也是静态的。

程序运行结束之后要把所有的静态对象销毁。调用析构函数。销毁的顺序是创建的顺序相反的。

全局的静态对象是什么时候构建的:在main函数之前就创建了

全局的对象前面加static是其它的意思。有其他功能。

static在不同的地方的含义是不同的。