this指针
作用:指向成员函数所作用的对象
非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针
#include<iostream>
using namespace std;
class Complex
{
public:
double real,imag;
void Print()
{
cout<<real<<","<<imag;
}
Complex(double r,double i):real(r),imag(i){ }
Complex AddOne()
{
this->real++;//等价于直接写real++
this->Print();//等价于Print();直接调用
return *this;
}
};
int main()
{
Complex c1(1,1),c2(0,0);
c2=c1.AddOne();//this指针,返回的是作用的对象,c1,再赋值给c2
//返回的是AddOne()作用的自身
return 0;
}
class A
{
int i;
public:
void Hello()
{
cout<<"hello"<<endl;
//若是cout<<this->i<<"Hello"<<endl;
则报错,*this是一个空指针,无指向对象,就不能输出i
}
};
int main()
{
A* p=NULL;
p->Hello();
}
注意
- 静态成员函数中不能使用this指针
- 静态成员函数并不具体作用于某个对象!
- 因此,静态成员函数的真实的参数个数=程序中写出的参数个数
静态成员变量
形式:在定义前面加了static关键字的成员
class CRectangle
{
private:
int w,h;
static int nTotalArea;
static int nTotalNumber;//静态成员变量
CRectangle(int _w,int _h)
{
w=_w;
h=_h;
}//构造函数
~CRectangle();//析构函数
static void PrintTotal();//静态成员函数
};
普通成员变量:每个对象都有各自的一份
静态成员变量:所有同类对象都共用一份
普通成员函数:必须具体作用于某个对象
静态成员函数:并不具体作用于某个对象
静态成员不需要通过对象就能访问
注意:
sizeof()运算符不会计算静态成员变量
静态成员变量本质上是全局变量,哪怕一个对象都不存在,静态成员变量也存在
静态成员函数本质上是全局函数
必须在定义类的文件中对静态成员变量进行一次说明
即拿到全局变量的位置进行声明
int CRectangle::nTotalNumber=0;
可以初始化,也可以不初始化
否则编译能通过,链接不能通过
静态成员函数,不能访问非静态成员变量,也不能调用非静态成员函数
//因为静态成员函数,不能具体作用于某个对象
//不知道这个变量是哪个对象的
!!!
在生成类的时候,有时候的生成是利用复制构造函数生成的,但是自动生成的复制构造函数并不会使得总数和总面积增加。
可是这些复制构造函数生成的对象,消亡时依然走析构函数使得总数和总面积变少。
目的:
- 将某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解
解决上一节问题:
为什么要自己写复制构造函数
- 防止静态成员变量无故减少。
成员对象和封闭类
有成员对象的类就叫做封闭类
#include<iostream>
#include<algorithm>
using namespace std;
class CTyre//轮胎类
{
private:
int radius;//半径
int width;//宽度
public:
CTyre(int r,int w):radius(r),width(w){ }//构造函数
//冒号后面表示 初始化列表
};
class CEngine
{
};
class CCar
{
private:
int price;//价格
CTyre tyre;
CEngine engine;//成员对象
public:
CCar(int p,int tr,int tw):price(p),tyre(tr,tw){ }
};
int main()
{
CCar car(20000,17,225);
}
注意:
- 在上述例子中,CCar如果不定义构造函数,语句会编译出错。因为编译器不知道,car.tyre该怎样初始化
- 任何生成封闭类对象的语句,都要让编译器明白,对象中的成员对象,是需要怎样进行初始化
- 即一定要写封闭类的构造函数的初始化列表
- 成员对象初始化列表中的参数可以时任意复杂的表达式,可以包括函数,变量等。
- 封闭类对象消亡时,先执行封闭类的析构函数,然后再执行成员对象的析构函数。次序和析构函数的调用次序相反。
封闭类的复制构造函数
#include<iostream>
#include<algorithm>
using namespace std;
class A
{
public:
A(){cout<<"default"<<endl;}
A(A&a){cout<<"Copy"<<endl;}
};
class B
{
A a;
};
int main()
{
B b1;//default
B b2(b1);//Copy
//输出copy说明b2.a是用类A的复制构造函数初始化的
//而且调用复制构造函数时的实参就是b1.a
}
常量对象、常量成员函数
在前面加const关键字,使得对象无法被修改
成员函数里,在后面加const
- 常量成员函数执行期间不应修改其所作用的对象
- 因此,在常量成员函数中不能修改成员变量的值
- 静态成员变量除外
- 也不能调用同类的非常量成员函数
- 静态成员函数除外
#include <iostream>
using namespace std;
class Sample
{
public:
int value;
void GetValue()const{
value=0;//error
func()=0;//error
}
void func(){ };
Sample(){ }
};
int main()
{
const Sample o;
o.value=100;//error常量对象不可被修改
o.func();//error常量对象上面不能执行非常量成员函数
o.GetValue();//ok
return 0;
}
注意:
- 两个成员函数,名字和参数表都一样,但是一个是const,一个不是,算重载
#include <iostream>
using namespace std;
class CTest
{
private:
int n;
public:
CTest(){n=1; }
int GetValue()const {return n;}
int GetValue() {return 2*n;}
};
int main()
{
const CTest objTest1;
CTest objTest2;
//常量对象就会调用常量版本的函数
cout<<objTest1.GetValue()<<","<<objTest2.GetValue()<<endl;
}
友元
友元分为友元函数和友元类两种
- 友元函数:一个类的友元函数可以访问该类的私有成员
- 可以将一个类的成员函数**(包括构造、析构函数)**说明为另一个类的友元。
#include <iostream>
using namespace std;
class CCar;
class CDriver
{
public:
void ModifyCar(CCar* pCar);//CCar指针
};
class CCar
{
private:
int price;
friend int MostExpensiveCar(CCar cars[],int total);
//这个函数放到类里声明友元之后,可以使得这个函数访问该类的私有成员
friend void CDriver::ModifyCar(CCar* pCar);
//声明友元:友元函数不一定是这个类的成员函数,可以是别的类的成员函数
//也可以是某个全局函数
};
void CDriver::ModifyCar(CCar* pCar)
{
pCar->price+=1000;
}//在CDriver里的成员函数,可以访问CCar里的成员函数(基本条件是CCar声明其为友元函数
int MostExpensiveCar(CCar cars[],int total)
{
int tmpMax=-1;
for(int i=0;i<total;i++)
{
if(cars[i].price>tmpMax)
tmpMax=cars[i].price;
}
return tmpMax;
}
//这是个全局函数,也可以访问CCar里的price,就得CCar里声明友元
int main()
{
return 0;
}
友元类:
- 如果A是B的友元类,那么A的成员函数可以访问B的私有成员
- 即整个B都是A的友元
class CCar
{
private:
int price;
friend class CDriver;//说明整个CDriver为友元类
};
//CDriver类在使用CCar的私有成员时,要在类里有一个CCar的对象
class CDriver
{
public:
CCar mycar;
//必须有这个声明
void MOdifyCar()
{
mycar.price+=1000;
}
}
!!!友元类之间的关系不能传递,不能继承
比如A是B的友元,C是A的友元,但C不是B的友元,不能传递