参考mooc魏英《C++程序设计》
文字是魏老师的讲解,纯手打,ppt上没有。
为什么会用到静态成员:现在大型应用程序都是由多个程序员所开发的,那么多个程序员就需要使用一个共同都能使用的数据来解决一些问题,采用静态数据成员解决这一问题。
思考一下现在我们需要统计员工的总人数,能不能在这个员工类中增加一个成员专门用来存放总人数呢?这样做是不好的:1.每个对象都要增加一个这样的成员,对存储空间是一种浪费。对于公司来说,总人数只有一个值,那么每个对象都要增加一个这样的成员,浪费存储空间。2.使用不方便,当总人数改变时,意味着每个对对象里面成员里的值都要改变。
增加静态数据成员解决这一问题:
其中的static int count是不属于任何一个对象的,也就是所有员工类的对象共享一个count,这个count属于一个类,而不属于任何一个对象,这样就大大减少了存储空间,并且当员工总人数修改后,只需要改一次就行了。
注意在类里面只是对这个静态变量进行了一个声明,但是它还不存在,要让它占有存储空间并存放数据,就要在类外对它做一个定义。
其他数据成员为什么不用在类外做定义呢?
当生成对象的时候,这个对象就会被分配存储空间。静态数据成员不属于每个对象,而是属于类,一个类只有一个数据成员,所以需要在类外对其定义并赋初值。
在构造函数里添加了一个count++,则每创建一个Data类的对象,都会调用构造函数,count都会加一,最后统计这个count的值时就能知道创建了多少个这个类的对象。
静态成员如果定义为私有成员,同样只有类里面的成员才能使用这个静态成员。如果是公有的在类外就可以直接访问。
成员函数也可以是静态的
静态数据成员是不用对象进行调用的,直接 类名::静态成员名 就可以被调用。静态成员函数既可以通过 类名::静态函数名 调用也可以通过 对象.静态函数名 调用。
静态成员函数是专门用来访问静态成员的
A处为什么不直接输出s_total的值呢?因为s_total是private类型的,类外不能直接访问。只能通过gettotal()这个public类型的函数去调用它。
B处出错原因:静态成员函数不能调用非静态成员。
C处非静态成员函数是可以调用静态成员函数的。反之不行。
在测试时发现静态成员初始化必须在类的.cpp源文件中初始化,否则会报错。
base.h
#pragma once
#include<iostream>
#include<ctime>
#include<windows.h>//在Linux和Mac下要换成 unistd.h 头文件
class Base
{
public:
Base(int a=0,int b=0);
Base(const Base &obj);
~Base();
public:
int getCount() const { return m_count; }
time_t getTime() const { return m_time; }
private:
int m_a;
int m_b;
time_t m_time;
public:
static int m_count;
};
base.cpp
#include "base.h"
Base::Base(int a, int b):m_a(a),m_b(b)
{
m_count++;
m_time = time((time_t*)NULL);
}
Base::Base(const Base &obj) {
this->m_a = obj.m_a;
this->m_b = obj.m_b;
this->m_count++;
this->m_time = time((time_t*)NULL);
}
Base::~Base(){}
int Base::m_count = 0;//静态成员初始化在类的.cpp源文件中初始化
main.cpp
#include "base.h"
using namespace std;
int main() {
Base obj1(10, 20);
cout << "obj1:count=" << obj1.getCount() << ",time" << obj1.getTime() << endl;
Sleep(3000);
Base obj2 = obj1;
cout << "obj2:count=" << obj1.getCount() << ",time" << obj2.getTime() << endl;
system("pause");
return 0;
}
当静态成员初始化不在类的.cpp源文件中初始化,比如在main.cpp中初始化(int Base::m_count=0)时。会出现如下重定义的错误:
改成如下:
Base::m_count = 0;
会出现如下错误:
总之得出结论:静态成员初始化需要在类的.cpp源文件中初始化