//作者:马博
//创作时间:2013年12月6日
静态成员函数和静态成员方法
同一个类定义的每一个对象之间都是互补干扰的,也就是说,每一个类对象都有其独立的成员变量。但有时希望其中的一个或者几个数据可以共同使用,该怎么办呢?
打个比方,有一家全国的连锁商店,有很多个省市开办了多家分店,商品价格全国统一。但还是希望调整价格的时候,就要对没一家连锁闪电的价格进行更改。这家全国的连锁商店就
像是类,而在全国各个地方的连锁商店就像是类的对象,进行价格的调整就像是修改对象中的成员变量。这么多的对象,并且每一个都要进行修改,无疑是非常麻烦的
为了解决这个问题,以同时响应所有对象的数据修改,可以将类中的成员变量修饰成静态成员变量。
例如(1)
class CShop
{
public:
void ShowPrice();
private;
static int m_price; //将m_price声明为静态成员变量
int m_size;
};
在类中将m_price变量中声明成静态成员变量,则该变量就被所有的CShop类的对象所共有。
静态成员变量在内存中只创建一份,并不是每一个对象都有自己的静态成员变量。因此,当静态成员变量改变时,所有对象中的这个变量也是同时改变的。
下面是关于静态成员变量的一些说明:
(A)只要在类中声明静态成员变量,及时不定义对象,也可以为静态成员变量来分配空间,进而可以使用静态变量。
例如:int p = CShop::m_price;
(B)静态成员变量虽然在类中,但它并不是随对象的建立而分配空间的,也不是随对象的撤销而释放(一般的成员在对象建立时会分配空间,在对象撤销时会释放)。静态成员变量
是在程序编译时分配空间,而在程序结束时释放空间。
(C)初始化静态成员变量要在类的外面进行。初始化的格式如下:
数据类型 类名::静态成员变量 = 初值;
例如:
int CShop::m_price = 100; //不必要在初始化语句中加上关键字static
(D)既可以通过类名来对静态成员变量进行引用,也可以通过对象名来对静态成员变量进行引用。
例如(2)
#include "stdafx.h"
#include <iostream>
using namespace std;
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowSize();
static int m_price; //声明一个共有的静态成员变量
private:
int m_size; //声明一个私有的成员变量
};
CShop::CShop(int size)
{
m_size = size;
}
void CShop::ShowSize()
{
cout<<"商品的价格是:"<<m_size<<endl;
}
int CShop::m_price = 100; //初始化静态成员变量
int main()
{
CShop shop(50); //定义一个CShop对象
cout<<"商品的价格是:"<<CShop::m_price<<endl; //通过类名调用静态成员变量
shop.ShowSize();
cout<<"商品的价格是:"<<shop.m_price<<endl;
return 0;
}
通过类名和通过对象调用静态成员变量都是可行的,但是要将静态成员变量作为共有成员变量。这样就不符合数据封装的理念,所以还是在类中提供一个借口,用函
数调用类中的成员变量对数据进行修改。
但是用成员函数调用静态成员变量时,必须要有对象存在。有时希望实在产生对象之前调用就更该类中的数据,像每天全国连锁每天都要把价格调整好之后再开门营业一样。
例如(3)
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowPrice();
void ShowSize();
int ChangePrice(int price); //成员函数更改私有成员变量
private:
int m_size; //声明一个私有成员变量
static int m_price; //声明一个私有静态成员变量
};
int CShop::m_prine = 100; //初始化静态成员变量
int CShop::ChangePrice(int price)
{
m_price = price;
return m_price;
}
int main()
{
CShop::ChangePrice(200); //不能被调用!因为没有类的对象
return 0;
}
因为在主函数main中没有产生类的对象,所以不能对类中的成员函数进行调用。这样就不能起到对象产生之前就对类中数据修改的作用。
不过,成员函数也可以定义为静态的。在类中成员函数的声明前面加上关键字static,即可使其成为静态成员变量。使用静态成员函数就可以不依赖于对象。
例如(4)
#include "stdafx.h"
#include <iostream>
using namespace std;
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowSize();
static void ShowPrice(); //声明静态成员函数来显示价格
static int ChangePrice(int price); //声明静态成员函数来更改价格
private:
int m_size; //声明一个私有成员变量
static int m_price; //声明一个私有静态成员变量
};
CShop::CShop(int size)
{
m_size = size;
}
void CShop::ShowSize()
{
cout<<"商品数量:"<<m_size<<endl;
}
void CShop::ShowPrice()
{
cout<<"商品价格:"<<m_price<<endl;
}
int CShop::ChangePrice9int price)
{
m_price = price;
return m_price;
}
int CShop::m_price = 100; //初始化静态成员变量
int main()
{
CShop::ShowPrice();
CShop::ChangePrice(200);
CShop::ShowPrice();
CShop shop(50);
shop.ShowSize();
shop.ShowPrice();
return 0;
}
在类中声明成员函数为静态成员函数:static void ShowPrice();和static int ChangePrice(int price);
通过上面的实例,可以发现在主函数中虽然没有定义类的对象,但是依然可以调用类的函数,对类中的数据进行更改。
这样就实现了在产生对象之前就做成更改的操作。
普通成员函数和静态成员函数的区别是:
普通成员函数在参数传递时编译器会隐藏一个this指针,通过this指针来确定调用内产生的哪个对象;但是静态成员函数没有this指针,不知道应该访问哪个对象
中的数据,所以在程序中不可以用静态成员函数访问类中的普通变量。
//创作时间:2013年12月6日
静态成员函数和静态成员方法
同一个类定义的每一个对象之间都是互补干扰的,也就是说,每一个类对象都有其独立的成员变量。但有时希望其中的一个或者几个数据可以共同使用,该怎么办呢?
打个比方,有一家全国的连锁商店,有很多个省市开办了多家分店,商品价格全国统一。但还是希望调整价格的时候,就要对没一家连锁闪电的价格进行更改。这家全国的连锁商店就
像是类,而在全国各个地方的连锁商店就像是类的对象,进行价格的调整就像是修改对象中的成员变量。这么多的对象,并且每一个都要进行修改,无疑是非常麻烦的
为了解决这个问题,以同时响应所有对象的数据修改,可以将类中的成员变量修饰成静态成员变量。
例如(1)
class CShop
{
public:
void ShowPrice();
private;
static int m_price; //将m_price声明为静态成员变量
int m_size;
};
在类中将m_price变量中声明成静态成员变量,则该变量就被所有的CShop类的对象所共有。
静态成员变量在内存中只创建一份,并不是每一个对象都有自己的静态成员变量。因此,当静态成员变量改变时,所有对象中的这个变量也是同时改变的。
下面是关于静态成员变量的一些说明:
(A)只要在类中声明静态成员变量,及时不定义对象,也可以为静态成员变量来分配空间,进而可以使用静态变量。
例如:int p = CShop::m_price;
(B)静态成员变量虽然在类中,但它并不是随对象的建立而分配空间的,也不是随对象的撤销而释放(一般的成员在对象建立时会分配空间,在对象撤销时会释放)。静态成员变量
是在程序编译时分配空间,而在程序结束时释放空间。
(C)初始化静态成员变量要在类的外面进行。初始化的格式如下:
数据类型 类名::静态成员变量 = 初值;
例如:
int CShop::m_price = 100; //不必要在初始化语句中加上关键字static
(D)既可以通过类名来对静态成员变量进行引用,也可以通过对象名来对静态成员变量进行引用。
例如(2)
#include "stdafx.h"
#include <iostream>
using namespace std;
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowSize();
static int m_price; //声明一个共有的静态成员变量
private:
int m_size; //声明一个私有的成员变量
};
CShop::CShop(int size)
{
m_size = size;
}
void CShop::ShowSize()
{
cout<<"商品的价格是:"<<m_size<<endl;
}
int CShop::m_price = 100; //初始化静态成员变量
int main()
{
CShop shop(50); //定义一个CShop对象
cout<<"商品的价格是:"<<CShop::m_price<<endl; //通过类名调用静态成员变量
shop.ShowSize();
cout<<"商品的价格是:"<<shop.m_price<<endl;
return 0;
}
通过类名和通过对象调用静态成员变量都是可行的,但是要将静态成员变量作为共有成员变量。这样就不符合数据封装的理念,所以还是在类中提供一个借口,用函
数调用类中的成员变量对数据进行修改。
但是用成员函数调用静态成员变量时,必须要有对象存在。有时希望实在产生对象之前调用就更该类中的数据,像每天全国连锁每天都要把价格调整好之后再开门营业一样。
例如(3)
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowPrice();
void ShowSize();
int ChangePrice(int price); //成员函数更改私有成员变量
private:
int m_size; //声明一个私有成员变量
static int m_price; //声明一个私有静态成员变量
};
int CShop::m_prine = 100; //初始化静态成员变量
int CShop::ChangePrice(int price)
{
m_price = price;
return m_price;
}
int main()
{
CShop::ChangePrice(200); //不能被调用!因为没有类的对象
return 0;
}
因为在主函数main中没有产生类的对象,所以不能对类中的成员函数进行调用。这样就不能起到对象产生之前就对类中数据修改的作用。
不过,成员函数也可以定义为静态的。在类中成员函数的声明前面加上关键字static,即可使其成为静态成员变量。使用静态成员函数就可以不依赖于对象。
例如(4)
#include "stdafx.h"
#include <iostream>
using namespace std;
class CShop //声明一个CShop类
{
public:
CShop(int size);
void ShowSize();
static void ShowPrice(); //声明静态成员函数来显示价格
static int ChangePrice(int price); //声明静态成员函数来更改价格
private:
int m_size; //声明一个私有成员变量
static int m_price; //声明一个私有静态成员变量
};
CShop::CShop(int size)
{
m_size = size;
}
void CShop::ShowSize()
{
cout<<"商品数量:"<<m_size<<endl;
}
void CShop::ShowPrice()
{
cout<<"商品价格:"<<m_price<<endl;
}
int CShop::ChangePrice9int price)
{
m_price = price;
return m_price;
}
int CShop::m_price = 100; //初始化静态成员变量
int main()
{
CShop::ShowPrice();
CShop::ChangePrice(200);
CShop::ShowPrice();
CShop shop(50);
shop.ShowSize();
shop.ShowPrice();
return 0;
}
在类中声明成员函数为静态成员函数:static void ShowPrice();和static int ChangePrice(int price);
通过上面的实例,可以发现在主函数中虽然没有定义类的对象,但是依然可以调用类的函数,对类中的数据进行更改。
这样就实现了在产生对象之前就做成更改的操作。
普通成员函数和静态成员函数的区别是:
普通成员函数在参数传递时编译器会隐藏一个this指针,通过this指针来确定调用内产生的哪个对象;但是静态成员函数没有this指针,不知道应该访问哪个对象
中的数据,所以在程序中不可以用静态成员函数访问类中的普通变量。
vc编译出错:illegal call of non-static member function
报错内容:编译时发现用调用静态成员函数的方法调用了非静态的成员函数出错原因:由于非静态成员函数只能用类的对象的指针调用,而静态成员函数对每个类只有一份拷贝,所以要用类名区分和调用。
可能性1:声明此成员函数时应该声明为静态的,即在返回类型和函数名之前加关键字 static 。
可能性2:调用的的确不能是静态函数,此时应该在调用的类里加入一个成员变量,这个变量就是为被调用的函数的类的对象。然后通过这个对象去调用函数。
可能性3:静态多态性的情况。调用类和被调用类是子类和基类的关系,并且子类重写了基类里的成员函数,那么调用的时候需要用::双冒号运算符区分所调用的是子类还是基类的成员。