对象的使用
来源:互联网 发布:淘宝店铺地址能改吗 编辑:程序博客网 时间:2024/06/05 09:05
static成员
- 对特定类型的全体对象而言,有时候需要访问一个全局的变量。比如说统计某种类型对象已创建的数量;
- 如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这是我们可以用类的静态成员来解决这个问题;
- 非static数据成员存在于类类型的每个对象中,static数据成员独立该类的任意对象存在,它是与类关联的对象,不与类对象关联。
static成员声明、定义与初始化
- static成员需要在类定义体外进行初始化与定义
/*---------------------示例代码------------------------*///CountedObject.h #ifndef _COUNTED_OBJECT_H_#define _COUNTED_OBJECT_H_class CountedObject{public: CountedObject(); ~CountedObject(); static int count_; //静态成员的引用性声明};#endif //_COUNTED_OBJECT_H_//CountedObject.cpp #include "CountedObject.h"int CountedObject::count_ = 0; //静态成员的定义性声明,此时不需要指定static //静态成员的初始化也必须放在文件作用域CountedObject::CountedObject(){ ++count_;}CountedObject::~CountedObject(){ --count_;}//01.cpp#include "CountedObject.h"#include<iostream>using namespace std;int main(void){ CountedObject ob1; cout << CountedObject::count_ <<endl; CountedObject* ob2 = new CountedObject; cout << CountedObject::count_ <<endl; delete ob2; cout << CountedObject::count_ <<endl; return 0;}
特殊的整型static const成员:整型static const成员可以在类定义体中初始化
#include<iostream>using namespace std;class Test{public: Test() {} ~Test() {} static const int x_ = 100; //静态常量整型成员的初始化可以直接在类体内进行};int main(void){ cout<<Test::x_<<endl;}
static成员优点
- static成员的名字是在类的作用域中,因此可以避免与其它类成员或全局对象名字冲突
- 可以实施封装,static成员可以是私有的,而全局对象不可以
- 阅读程序容易看出static成员与某个类相关联,这种可见性可以清晰地反映程序员的意图
当静态成员声明为私有时,需要提供接口函数
#ifndef _COUNTED_OBJECT_H_#define _COUNTED_OBJECT_H_class CountedObject{public: CountedObject(); ~CountedObject();public: static int GetCounnt();//为私有的静态成员提供接口函数private: static int count_; //静态成员的引用性声明};#endif //_COUNTED_OBJECT_H_int CountedObject::GetCounnt() //接口函数{ return count_;}
static成员函数
- static成员函数没有this指针
- static成员函数不可以访问非静态成员和非静态成员函数
- 非静态成员函数可以访问静态成员
class Test{public: Test(int y) : y_(y) { } ~Test() { } void TestFun() { cout<<"x="<<x_<<endl; //OK,非静态成员函数可以访问静态成员 TestStaticFun(); } static void TestStaticFun() { cout<<"TestStaticFun ..."<<endl; //TestFun(); Error,静态成员函数不能调用非静态成员函数 //cout<<"y="<<y_<<endl; Error,静态成员函数不能访问非静态成员 } static int x_; // 静态成员的引用性说明 int y_;};
类/对象大小计算
- 类大小计算遵循前面学过的结构体对齐原则
- 类的大小与数据成员有关与成员函数无关
- 类的大小与静态数据成员无关
- 虚函数对类的大小的影响
- 虚继承对类的大小的影响
四种对象的作用域与生存期
栈对象
隐含调用构造函数(程序中没有显示调用)
堆对象
隐含调用构造函数(程序中没有显示调用)
全局对象、静态全局对象
- 全局对象的构造先于main函数
- 已初始化的全局变量或静态全局对象存储于.data段中
- 未初始化的全局变量或静态全局对象存储于.bss段中
静态局部对象
- 已初始化的静态局部变量存储于.data段中
- 未初始化的静态局部变量存储于.bss段中
static用法总结
C语言中的用法
- 用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期长于该函数,使得函数具有一定的“状态”。使用静态变量的函数一般是不可重入的,也不是线程安全的,比如strtok(3);
- 用在文件级别(函数体之外),修饰变量或函数,表示该变量或函数只在本文件可见,其他文件看不到也访问不到该变量或函数。专业的说法叫“具有internal linkage”(简言之:不暴露给别的translation unit)。
C++中添加的用法
- 用于修饰类的数据成员,即所谓“静态成员”。这种数据成员的生存期大于class的对象(实例/instance)。静态数据成员是每个class有一份,普通数据成员是每个instance 有一份;
- 用于修饰class的成员函数,即所谓“静态成员函数”。这种成员函数只能访问静态成员和其他静态程员函数,不能访问非静态成员和非静态成员函数。
static与单例模式
- 保证一个类只有一个实例,并提供一个全局访问点
- 禁止拷贝
#include<iostream>using namespace std;class Singleton{public: static Singleton* GetInstance() //2. 提供一个全局访问点 { if(instance_ == NULL) { instance_ = new Singleton; //构造 } return instance_; } ~Singleton() { cout << "~Singleton ..."<<endl; }private: Singleton() //1. 将构造函数声明为私有的 { cout<< "Singleton ..."<<endl; } Singleton(const Singleton& other); // Singleton& operator=(const Singleton& other); //3. 将拷贝构造函数与等号运算符都声明为私有的,斌企鹅不提供其实现方式,那么就可以禁止拷贝了 static Singleton* instance_;};Singleton* Singleton::instance_;int main(void){ Singleton* s1 = Singleton::GetInstance();// Singleton* s2 = Singleton::GetInstance();// 二者调用的是同一个实例 return 0;}
需要注意的是以上程序运行时系统是不会调用析构函数的,所以需要进一步改造
- 方案一:
#include<iostream>using namespace std;class Singleton{public: static Singleton* GetInstance() { if(instance_ == NULL) { instance_ = new Singleton; // } return instance_; } ~Singleton() { cout << "~Singleton ..."<<endl; } class Garbo //1. 提供一个嵌套类,在该类中进行释放 { public: ~Garbo() { if(Singleton::instance_ != NULL) { delete Singleton::instance_; } } };private: Singleton() { cout<< "Singleton ..."<<endl; } Singleton(const Singleton& other); Singleton& operator=(const Singleton& other); static Singleton* instance_; static Garbo garbo_; //2. 当该对象生存周期结束时自动调用析构函数,从而达到};Singleton::Garbo Singleton::garbo_; // 3. 此处必须声明Singleton* Singleton::instance_;int main(void){ Singleton* s1 = Singleton::GetInstance(); Singleton* s2 = Singleton::GetInstance(); return 0;}
- 方案二(推荐):
#include<iostream>using namespace std;class Singleton{public: static Singleton& GetInstance() //全局访问点 { static Singleton instance; //局部静态成员 return instance; } ~Singleton() { cout << "~Singleton ..."<<endl; }private: Singleton() { cout<< "Singleton ..."<<endl; } Singleton(const Singleton& other); Singleton& operator=(const Singleton& other);};int main(void){ Singleton& s1 = Singleton::GetInstance(); Singleton& s2 = Singleton::GetInstance(); return 0;}
const成员函数
- const成员函数不会修改对象的状态
- const成员函数只能访问数据成员的值,而不能修改它
class Test{public: Test(int x):x_(x) {} int GetX() const { return x_; }private: int x_;};
const对象
- 如果把一个对象指定为const,就是告诉编译器不要修改它;
- const对象的定义:
const 类名 对象名(参数表) - const对象不能调用非const成员函数
int main(void){ const Test t(10); //const对象,对象的状态不能被更改,不能调用非const成员函数 cout << t.GetX() << endl; //GetX()为const成员函数,因此t可以调用 return 0;}
mutable
- 用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改
class Test{public: Test(int x):x_(x),outputtimes_(0) {} int GetX() const { return x_; } void OutPutX() const { cout << "x = "<<x_<<endl; outputtimes_++; //outputtimes_已被声明为mutable,此处可以修改它的值 } int GetOutPutTimes() const { return outputtimes_; }private: int x_; mutable int outputtimes_;};
0 0
- 函数对象的使用
- Request对象的使用
- 函数对象的使用
- Request对象的使用
- XMLHttpRequest 对象的使用
- cookie对象的使用
- AO对象的使用
- OutlookSession对象的使用
- XMLHttpRequst对象的使用
- GDI对象的使用
- ORACLE 对象的使用
- Intent对象的使用
- 函数对象的使用
- LOB对象的使用
- 活动对象的使用
- CArchive的对象使用
- Dictionary对象的使用
- id对象的使用
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- 使用第三方应用授权时应用调用OAuth一直出现redirect_uri参数错误
- 苹果App Store审核指南中文翻译(更新)
- 公元2015年11月24日。雨。
- 安装cocoapods
- 对象的使用
- redhat下设置系统时间
- TextView ellipsize=“marquee” 跑马灯效果不能实现,解决
- 分区助手专业版5.0下载与使用方法
- C#多线程|匿名委托传参数|测试您的网站能承受的压力
- css3 em单位的使用方法
- TouchSlider 实现(PC及移动端触摸界面)的幻灯slider效果
- 黑客是如何发现女朋友出轨的
- 导入android studio 项目错误:Error:(1, 0) Plugin with id 'com.android.application' not found