static 与 this 指针
static
当类被多次实例化后,一般数据成员会有多份,而成员函数只有一份,通过this指针确定当前数据成员是在那个对象中被调用。但是类中的static成员却不尽相同:
static成员数据
类中的static数据成员,在类中只有一份,可以理解成,类范围内的静态全局变量。
类中的static数据成员必须在类外定义并初始化,类中声明。
就像静态变量,类中的static数据成员也只初始化一次,并在整个程序的声明周期中一直存在。
static成员函数
类的static成员函数,与普通成员函数不同,它被调用时不会传递this指针,也就是说他没有对象的概念。
类中的static成员函数,只能使用类中的static数据成员。(因为没有this指针不能确认那个普通数据成员可以使用)
static成员函数的调用方式有两种:
1.通过对象调用
2.通过class name调用
class complex{
private:
double re, im;
static int instance_cnt;
public:
complex(double _re = 0, double _im = 0) : re(_re), im(_im) { instance_cnt++; }
complex(const complex & c):re(c.re), im(c.im) { instance_cnt++; }
static int get_instance_num(){ return instance_cnt; } //返回当前类共有多少对象
};
int complex::instance_cnt = 0;
int main(){
complex c1(1,2);
complex c2(c1);
complex c3 = c2;
complex *pc = new complex(2,3);
cout << "complex class has " << complex::get_instance_num() << " objects in total." << endl;//通过类名调用
delete pc;
pc = NULL;
cout << "now the complex class has " << c1.get_instance_num() << " objects left." << endl;//通过类对象调用
}
以上运行结果:
注:static 成员数据在类外定义的时候不需要使用static关键字:
this指针
类的成员函数都有一个隐藏的参数——this指针,当数据成员被调用时都会隐式传入this指针。但是,对于类中的static成员函授,不会传入this指针,所以static成员函数无法处理对象的成员数据,而只能处理类中的static数据。
放在private区中的constructor函数(singleton)
类的构造函数通常为public,这样才能构造出很多实例。但是,在设计模式中有一种专门把构造函数设计成私有成员,其作用就是保证一个类只能有一个实例,并提供一个全局唯一的访问点。这种设计模式叫做单例设计模式(singleton)
class Singleton{
public:
static Singleton* getInstance(){
if(!pIns){
pIns = new Singleton();
}
return pIns ;
}
static void dosth(){……}
static void destory(){
if(pIns){
delete pIns;
pIns = NULL;
}
}
private:
singleton(){}
static singleton * pIns;
};
//调用:
int main(){
for(int i = 0; i < 10; ++i){
Singleton *ps = Singleton::getInstance();//通过全局访问点访问,其实只有一个实例,并不是每次循环都创建
Singleton::dosth();
}
Singleton::destroy();
return 0;
}
singleton的特点:
不调用getInstance就没有Singleton类的实例存在,调用一次后,不管再调用多少次,都只有一个实例。
cout——一种ostream,重载了“<<”操作符
cout是一种ostream类,在其内部针对各种内置数据类型多次重载了操作符“<<”,使其可以输出内置数据类型的各种实例。因此用户定义的类中,如果想重载操作符"<<",必须定义成全局的操作符重载函数,第一个参数是ostream cout,第二个参数是自定义的类,这样才符合cout 在 “<<”左边,实例在右边的日常使用习惯。
complex类,重载操作符“<<”的代码示例:
class complex{
private:
double re, im;
public:
friend ostream & operator<<(ostream & os, const complex& c);
};
ostream & operator<<(ostream & os, const complex& c){
os << "(" << c.re << "," << c.im << ")" ;
return os;
}
int main(){
complex c1(1,2);
cout << c1 << endl;
}
如果把操作符“<<”的重载设计成类成员函数,则其参数将只能有一个ostream类型,在调用的时候会默认出入this指针作为左值,这样对其的调用形式将是:“c1 << cout”,是不是很奇怪呢?完全不符合我们日常的使用习惯。
因此切记:对于自定义的类,其操作符“<<”的重载函数必须要写成全局变量才好!
类模板与函数模板
类模板
使用时必须显示指定类型
函数模板
使用时编译器会作参数推导,不用显示指定类型
namespace
使用命令的方式引用
语法:using namespace <名字空间名>
使用声明的方式引用
语法:using <名字空间名>::<函数名>
不使用using引用
语法:在使用的地方,直接以 <名字空间名>::<函数名> 的方式使用