一、 静态成员
1、 静态成员变量
class 类名{
static数据类型 数据明;//声明
};
数据类型 类名::变量名=初值;//定义和初始化
1) 静态成员变量不属于对象
2) 不能在构造函数中被定义和初始化,需要在类的外部单独地定义及初始化
3) 可以通过类名直接访问,也可以通过对象访问
4) 静态成员变量存放在全局区(代码段和BS),普通成员变量在栈区。
5) 静态成员使用受到访问控制属性的约束
1#include<iostream>
2using namespace std;
3class A{
4public:
5 int m_data;
5// pvivate:
6 static int s_data;
7};
8int A::s_data=100;
9int main(void){
10 Aa;
11 cout<<sizeof(a)<<endl;//4
12 cout<<A::s_data<<endl;//100
13 cout<<a.s_data<<endl;//也可以通过对象访问
14 }
2、 静态成员函数
1) 可以通过类名直接访问,也可以通过对象访问
2) 静态成员函数没有this指针,因此也没有const属性
3) 和普通成员函数一样受访问控制限定符的约束
4) 静态成员函数存放在全局区(代码段和BS)
1#include<iostream>
2using namespace std;
3class A{
4public:
5//private:
6 static voidfunc(void)/*const*/{
7 cout<<"静态成员函数"<<endl;
8 }
9};
10int main(void){
11 A::func();//作用域
12 return 0;
13 }
3、 静态成员函数只能访问静态成员;非静态成员函数既能访问静态成员,也能访问非静态成员(因为静态成员函数没有this指针)
1#include<iostream>
2using namespace std;
3class A{
4public:
5 static void func(void)/*const*/{
6 cout<<"静态成员函数"<<endl;
7 cout<<s_data<<endl;
8 //cout<<m_data<<endl;
9 //静态成员函数只能访问静态成员
10 }
11 void func2(void){
12 cout<<"非静态成员函数"<<endl;
13 cout<<s_data<<endl;
14 cout<<m_data<<endl;
15 //非静态成员函数既能访问静态成员,也能访问非静态成员
16 }
17 static int s_data;
18 int m_data;
19};
20int A::s_data=100;
21int main(void){
22 Aa;
23 a.m_data=200;
24 a.func();//A::func()
25 a.func2();
26 return 0;
27 }
tarena@tarena-virtual-machine:~/day41$./a.out
静态成员函数
100
非静态成员函数
100
200
4、 单例模式
单例:只允许存在唯一的对象实例
1) 禁止在类的外部创建对象:私有化构造函数
2) 类自己内部维护唯一的对象:静态成员变量
3) 提供访问该对象的方法:静态成员函数
具体实现方式:
-à饿汉式:无论用与不用单例对象,程序启动即创建
1#include<iostream>
2using namespace std;
3class A{
4public:
5 static A&getInstance(void){
6 return s_instance;
7 }
8private:
9 A(int data=0):m_data(data){}
10// A(const A& that);//不写拷贝构造函数,编译器则提供一个缺省的公有构造函数
11 int m_data;
12 static A s_instance;//唯一对象
13};
14 AA::s_instance(1234);
15int main(void){
16// A a;error
17// A *pa=new A(4321);error
18 A& a1=A::getInstance();
19 A& a2=A::getInstance();
20 cout<<"&a1="<<&a1<<endl;
21 cout<<"&a2="<<&a1<<endl;
22 return 0;
23 }
-à懒汉式:单例对象用时再创建,不用了即销毁
1#include<iostream>
2using namespace std;
3class A{
4public:
5 static A&getInstance(void){
6 if(!s_instance){ //保证只new一个空间
7 s_instance=newA(1234);
8 }
9 ++s_counter;
10 return *s_instance;
11 }
12 void release(void){
13 if(s_counter&&--s_counter==0){//判断是否最后一个对象在使用
14 delete this;//自销毁
15 }
16 }
17private:
18 A(int data=0):m_data(data){
19 cout<<"A::A()"<<endl;
20 }
21 ~A(void){
22 cout<<"A::~A()"<<endl;
23 s_instance=NULL;
24 }
25 A(const A& that);
26 int m_data;
27 static A* s_instance;//唯一对象
28 static int s_counter;
29};
30A* A::s_instance=NULL;//初始化
31int A::s_counter=0;//记录单例对象别名数目
32int main(void){
33// A a;error
34// A *pa=new A(4321);error
35 A& a1=A::getInstance();
36 A& a2=A::getInstance();
37 A& a3=A::getInstance();
38 cout<<"&a1="<<&a1<<endl;
39 cout<<"&a2="<<&a1<<endl;
40 cout<<"&a3="<<&a1<<endl;
41 a1.release();
42 a2.release();
43 a3.release();//delete
44 return 0;
45 }
tarena@tarena-virtual-machine:~/day41$./a.out
A::A()
&a1=0x8c88008
&a2=0x8c88008
&a3=0x8c88008
A::~A()
二、 成员指针(了解)
1、成员变量指针
1)定义:
类型 类名::*成员指针变量名=&类名::成员变量
例:
class student{
string m_name;
};
//成员变量指针、
string student::*pname=&student::m_name’
student s;
string*p=&s.name;//普通指针
2)使用:
对象 .* 成员指针变量名;
“.*”成员指针解引用运算符
对象指针->*成员指针变量名
“->*”间接成员指针解引用运算符
1 #include<iostream>
2 using namespace std;
3 class Student{
4 public:
5 Student(const string& name):m_name(name){}
6 string m_name;
7 };
8 int main(void){
9 //成员变量指针的本质就是类中特定成员还在对象中的相对地址
10 string Student::*pname=&Student::m_name;
11 Student s1("张飞");
12 Student s2("张二");
13 cout<<s1.*pname<<endl;;
14 Student* ps=&s2;
15 cout<<ps->*pname<<endl;
16 }
2、成员函数指针
1) 定义
返回类型 (*类名::成员函数指针)(形参表)=&类名::成员函数名
2) 使用
(对象.*成员函数指针)(实参表)
(对象指针->*成员函数指针)(实参表)
1 #include<iostream>
2 using namespace std;
3 class Student{
4 public:
5 Student(const string& name):m_name(name){}
6 void who(){
7 cout<<m_name<<endl;
8 }
9 private:
10 string m_name;
11 };
12 int main(void){
13 void(Student::*pwho)(void)=&Student::who;
14 Student s1("张三");
15 Student s2("李四");
16 (s1.*pwho)();
17 Student* ps=&s2;
18 (ps->*pwho)();
19 //s1.who();
20 //s2.who();
21 return 0;
22 }
张三
李四
张三
李四
三、 操作符重载
例:复数:实部+虚部i
1 #include<iostream>
2 using namespace std;
3 class Complex{
4 public:
5 Complex(int r,int i):m_r(r),m_i(i){}
6 void print(void)const{
7 cout<<m_r<<'+'<<m_i<<'i'<<endl;
8 }/*
9 Complex add(Complex c){
10 return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
11 }*/
12 Complex operator+(Complex c){
13 return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
14 }
15 private:
16 int m_r;//实部
17 int m_i;//虚部
18 };
19 int main(void){
20 Complex c1(1,2);
21 Complex c2(3,4);
22 c1.print();
23 c2.print();
24 //c1+c2;error
25 // Complex c3=c1.add(c2);
26 Complex c3=c1+c2;//c1.operator+(c2)
27 c3.print();//4+6i;
28 return 0;
29 }
1+2i
3+4i
4+6i
1、双目操作符的重载:L#R
1.1 运算类双目操作符
----à左右操作数既可以是左值也可以是右值(a+10;a是左操作数,10是右操作数)
---à表达式的结果是右值
1) 成员函数形式
L#R==>L.operator#(R)成员函数调用的形式
1 #include<iostream>
2 using namespace std;
3 class Complex{
4 public:
5 Complex(int r,int i):m_r(r),m_i(i){}
6 void print(void)const{
7 cout<<m_r<<'+'<<m_i<<'i'<<endl;
8 }/*
9 Complex add(Complex c){
10 return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
11 }*/
12 /*从左到右三个const
13 *1)返回右值
14 *2)常引用:支持常右操作数
15 *3)常函数:支持常左操作数(常对象只能调用常函数) */
16 const Complex operator+(const Complex& c)const{
17 return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
18 }
19 private:
20 int m_r;//实部
21 int m_i;//虚部
22 };
23 int main(void){
24 const Complex c1(1,2);
25 const Complex c2(3,4);
26 c1.print();
27 c2.print();
28 //c1+c2;error
29 // Complex c3=c1.add(c2);
30 Complex c3=c1+c2;//c1.operator+(c2)
31 c3.print();//4+6i;
32 // (c1+c2)=c3; error
33 return 0;
34 }
2)全局函数形式
L#R==》::operator#(L,R)全局函数调用形式,函数返回的结果就是表达式的结果
注:friend关键字
通过friend关键字,可以把一个全局函数声明为某个类的友元,友元函数可以访问类中任何成员。
#include<iostream>
using namespace std;
class Complex{
public:
Complex(int r,int i):m_r(r),m_i(i){}
void print(void)const{
cout<<m_r<<'+'<<m_i<<'i'<<endl;
}/*
Complex add(Complex c){
return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
}*/
/*从左到右三个const
*1)返回右值 c3
*2)常引用:支持常右操作数 c2
*3)常函数:支持常左操作数(常对象只能调用常函数) c1
Complex c3=c1+c2;//c1.operator+(c2) */
const Complex operator+(const Complex&c)const{
return Complex(m_r+c.m_r,m_i+c.m_i);//返回构造匿名对象
}
private:
int m_r;//实部
int m_i;//虚部
//friend声明函数可以访问类中任何成员
friend const Complex operator-(constComplex& l,const Complex& r);
};
const Complexoperator-(const Complex& l,const Complex& r){
return Complex(l.m_r-r.m_r,l.m_i-r.m_i);
}
int main(void){
const Complex c1(1,2);
const Complex c2(3,4);
c1.print();
c2.print();
//c1+c2;error
// Complex c3=c1.add(c2);
Complex c3=c1+c2;//c1.operator+(c2)
c3.print();//i4+6i;
// (c1+c2)=c3; error
Complex c4=c1+c2+c3;
c4.print();//8+12i
c4=c3-c1;//operator(c3,c1)
c4.print();//3+4i
return 0;
}
1.2 赋值类的双目操作符
--à左操作数必须是左值,不能是常量
--à右操作既可以是左值,也可以是右值
--à表达式的结果是左值,就是左操作自身
1)成员函数形式
L#R==>L.operator#R
2)全局函数形式
L#R==>::operator#(L,R)
1 #include<iostream>
2 using namespace std;
3 class Complex{
4 public:
5 Complex(int r,int i):m_r(r),m_i(i){}
6 void print(void)const{
7 cout<<m_r<<'+'<<m_i<<'i'<<endl;
8 }
9 Complex& operator+=(const Complex& c){
10 m_r+=c.m_r;
11 m_i+=c.m_i;
12 return *this;
13 }
14 private:
15 int m_r;//实部
16 int m_i;//虚部
17 //友元函数可以定义在类的内部,但不属于类,还是一个全局函数,也没有this指
针
18 friend Complex& operator-=(Complex& l,const Complex& r){
19 l.m_r-=r.m_r;
20 l.m_i-=r.m_i;
21 return l;
22 }
23 };
24 int main(void){
25 Complex c1(1,2);
26 Complex c2(3,4);
27 c1+=c2;//c1.operator+=(c2);
28 c1.print();//4+6i
29 c1-=c2;//::operator-=(c1,c2);
30 c1.print();//1+2i
31 return 0;
32 }
2、插入和提取操作符重载:<< >>
cout <<a ;
cout<<b<<endl;
#include<iostream>
ostream cout;
friend ostream&operator<<(ostream& os,const RIGHT& right) {..}
举例:
1 #include<iostream>
2 using namespace std;
3 class Complex{
4 public:
5 Complex(int r,int i):m_r(r),m_i(i){}
6 /* void print(void)const{
7 cout<<m_r<<'+'<<m_i<<'i'<<endl;
8 }*/
9 //输出操作符<<重载是固定模版
10 friendostream& operator<<(ostream& os,const Complex& c){
11 os<<c.m_r<<'+'<<c.m_i<<'i';
12 }
13 private:
14 int m_r;//实部
15 int m_i;//虚部
16
17 };
18 int main(void){
19 Complex c1(1,2);
20 Complex c2(3,4);
21 //operator<<(cout,c1)
22 //cout<<endl
23 cout<<c1<<endl; //1+2i
24 cout<<c2<<endl; //3+4i
25 return 0;
26 }
练习:
实现3*3矩阵类,支持如下操作符:
+ - += -=