用 static 修饰的函数称为静态成员函数。是一个属于类域的全局函数。
1. 静态成员函数的特点
(1)仅在类域中可见
(2)不能声明为虚函数,即不能具有多态性。也不能声明为const,voladite类型。
(3)独立于类对象存在,没有this指针,即不能访问类对象,包括与类对象相关的非静态成员以及非静态成员函数。由于静态成员函数独立于类对象,在定义任何类对象前即可访问,但此时没有任何类对象实例化,所以静态函数式不可以直接访问类的非静态成员和非静态成员函数的。
2. 调用静态成员函数
(1) 类名::静态成员函数
(2) 类对象.静态成员函数
3. 静态成员函数访问类的成员
由前面所分析的,得知,
(1) 可以直接访问与具体类对象无关的对象,包括静态成员、静态成员函数。
(2) 不能直接访问与具体类对象相关的对象,包括非静态成员、非静态成员函数。
(3) 被访问属性与普通的非静态成员函数相同。
(4) 可以访问某一个类对象的所有成员,包括这个对象的非静态成员和非静态成员函数。只要将类对象作为参数,传递给静态函数,就可以对类对象的非静态对象了。
4. 静态成员函数的几个错误用法示例
(1) 调用非静态成员函数
#include <stdlib.h>
#include <iostream>
class apple
{
public:
void fun()
{
// nothing
}
static void static_fun()
{
fun();
}
};
int main(int argc, char **argv)
{
apple::fun();
return 0;
}
编译报错,静态成员函数不能调用非静态成员函数
(2)调用非静态成员
#include <stdlib.h>
#include <iostream>
class apple
{
public:
static int static_fun()
{
return count;
}
public:
int count;
};
int main(int argc, char **argv)
{
apple::static_fun();
return 0;
}
编译报错,如下
(3)正确的示例
#include <stdlib.h>
#include <iostream>
using namespace std;
class apple
{
public:
apple(int price)
:price(price)
{
}
void nothing()
{
//nothing
cout << "nothing";
}
static void static_nothing()
{
cout << "static_nothing";
}
static int static_access_static_member()
{
return count;
}
static void static_access_static_fun()
{
static_nothing();
}
static int static_access_non_static_member(apple &APPLE)
{
return APPLE.price;
}
static void static_access_non_static_fun(apple &APPLE)
{
APPLE.nothing();
}
public:
static int count;
private:
int price;
};
int apple::count = 10;
int main(int argc, char **argv)
{
apple one_apple(13);
cout << "----apple::static_access_static_member()----"
<< apple::static_access_static_member()
<< endl;
cout << "----apple::static_access_static_fun()----";
apple::static_access_static_fun();
cout << endl;
cout << "----apple::static_access_non_static_member(one_apple)----"
<< apple::static_access_non_static_member(one_apple)
<< endl;
cout << "----apple::static_access_non_static_fun(one_apple)----";
apple::static_access_non_static_fun(one_apple);
cout << endl;
return 0;
}
运行结果如下:
5. 静态成员函数的作用
从OOA/OOD的角度看,一切不需要实例化就可以有确定行为的函数都应该设计成静态的。有以下几点可以考虑:
(1)可以实现某些特殊的设计模式,如singleton
(2)可以将某些系统API的回调以静态函数的方式封装至类内部。因为系统API的回调函数都是与类对象状态无关的,如一个创建线程的函数,不会因为创建对象的不同,而有不同的实现。如果没有类静态函数,就只能将其定义为全局函数(非静态成员函数指针无法转换为全局函数指针),从而影响了OO的封装性。
(3)可以将不依赖与具体类对象的算法声明为静态函数。比如数学函数,sin、tan 等,这些函数没有必要属于任何一个对象,所以从类上调用要更好。
如定义一个数学类Math,调用Math::sin(3.14),如果非要用非静态函数,那就必须
Math math;
math.sin(3.14);
为了一个与类对象状态无关的数学函数,要引入对象的构造和析构,代价有点大。