在C++中,static成员属于整个类而不是某个对象。不管类创建了多少对象,static成员只存储一份供所有对象使用。
在使用static成员时,对于它的声明、初始化和使用经常感到困惑,在此结合例子说明,希望能加深读者对于static成员的理解。
类中static成员有两种,一是static成员变量,一种是static成员函数。首先,先分析一下static成员变量。
第一个例子:static、static const、const和枚举的初始化
class classA
{
const int ciNum;
enum{eNum=10}; //枚举在类声明时初始化
int arr[eNum];
public:
classA():ciNum(10){} //const变量只能在构造函数初始化列表中初始化
static int siNum;
static const int sciNum=10; //static const可在类声明时初始化
static const int sciNumOut;
};
int classA::siNum=10; //static变量必须在类外面初始化,但不需要加static修饰符
const int classA::sciNumOut=10; //static const可在类外面初始化,不加static,但要加cosnt
int main()
{
cout<<classA::siNum<<endl;
cout<<classA::sciNum<<endl;
cout<<classA::sciNumOut<<endl;
return 0;
}
编译通过
结论1:枚举在类声明时初始化;static const可在类声明中初始化,也可在类外面初始化;const和引用在构造函数初始化列表中初始化;static成员变量只能在类外面初始化
第二个例子:static成员变量的引用
class classA
{
public:
static int pub_siNum;
};
class classB: public classA{};
int classA::pub_siNum=10;
int main()
{
classA tempA;
classB tempB;
cout<<classA::pub_siNum<<endl;
cout<<tempA.pub_siNum<<endl;
cout<<classB::pub_siNum<<endl;
cout<<tempB.pub_siNum<<endl;
return 0;
}
编译通过
结论2:公有static成员变量可以通过类名或者类对象调用,方式为“类名+::”或者“对象名+.”或“对象指针+->”;公有继承类的调用方式与基类相同
class classA
{
static int pri_siNum;
};
class classB: public classA{};
int classA::pri_siNum=10; //初始化方式同公有static成员变量
int main()
{
classA tempA;
classB tempB;
cout<<classA::pri_siNum<<endl;
cout<<tempA.pri_siNum<<endl;
cout<<classB::pri_siNum<<endl;
cout<<tempB.pri_siNum<<endl;
return 0;
}
编译出错:error C2248: “classA::pri_siNum”: 无法访问 private 成员(在“classA”类中声明)
结论3:私有static成员不能被类外部函数访问,也不能被对象访问,对于继承类也是如此
接下来分析一下static成员函数:
第一个例子:static成员函数的引用
class classA
{
public:
static void init(){}
};
class classB: public classA{};
int main()
{
classA tempA;
classB tempB;
classA::init();
tempA.init();
classB::init();
tempB.init();
return 0;
}
编译通过
结论1:公有static成员函数可以通过类名或者类对象调用,方式为“类名+::”或者“对象名+.”或“对象指针+->”;公有继承类的调用方式与基类相同。而私有static成员函数不能通过类或对象调用
第二个例子,在类的static成员函数中使用类的非static成员
class classA
{
public:
int iNum;
static void output()
{
cout << ++siNum;
cout << iNum;
}
private:
static int siNum;
};
int classA::siNum=10;
int main()
{
classA tempA;
tempA.iNum=10;
tempA.output();
return 0;
}
编译出错:error C2597: 对非静态成员“classA::iNum”的非法引用
因为static成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非static成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。
结论2:static成员函数可以引用static成员变量,但不能引用非static成员
第三个例子,在类的非static成员函数中使用类的static成员
class classA
{
public:
int iNum;
void output()
{
cout << ++siNum;
cout << iNum;
}
private:
static int siNum;
};
int classA::siNum=10;
int main()
{
classA tempA;
tempA.iNum=10;
tempA.output();
return 0;
}
编译通过
结论3:类的非static成员函数可以引用static成员
第四个例子:static成员函数和非static成员函数的相互引用
class classA
{
public:
void outPut()
{
};
static void staticOutput()
{
outPut();
};
static void staticOutput2()
{
};
void outPut2()
{
staticOutput2();
};
};
int main()
{
classA tempA;
tempA.staticOutput();
tempA.outPut2();
cin.get();
return 0;
}
error C2352: “classA::outPut”: 非静态成员函数的非法调用
结论4:非static成员函数可以引用static成员函数,但static成员函数不能引用非static成员函数
通过以上的例子,可以总结如下:
static变量
- 枚举在类声明时初始化;static const可在类声明中初始化,也可在类外面初始化;const和引用在构造函数初始化列表中初始化;static成员变量只能在类外面初始化
- static成员必须先初始化再使用,在类的方法中初始化或者在main()开始之前、类的声明之后的特殊地带为它提供定义和初始化
- 公有static成员变量可以通过类名或者类对象调用,方式为“类名+::”或者“对象名+.”或“对象指针+->”;公有继承类的调用方式与基类相同
- 私有static成员不能被类外部函数访问,也不能被对象访问,对于继承类也是如此
static函数
- 公有static成员函数可以通过类名或者类对象调用,方式为“类名+::”或者“对象名+.”或“对象指针+->”;公有继承类的调用方式与基类相同。而私有static成员函数不能通过类或对象调用
- static成员函数可以引用static成员变量,但不能引用非static成员
- 非static成员函数可以引用static成员
- 非static成员函数可以引用static成员函数,但static成员函数不能引用非static成员函数
- 不能通过类名来调用类的非静态成员函数
* 欢迎关注本人博客 *