注意点:
该指针和静态成员函数
静态成员函数中不能使用这个指针!
因为静态成员函数并不具体作用与某个对象!
因此,静态成员函数的真实的参数的个数,就是程序中写出的参数个数!
静态成员:在定义前面加了静态关键字的成员。
基础定义及注意点:
- 普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
- 普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。
- 因此成员静态不需要通过对象就能访问。
- 成员静态变量本质上的英文全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。
- 设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。
- 成员静态函数本质上的英文全局函数。
- sizeof运算符不会计算静态成员变量。
- 在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。
如何访问静态成员
class CRectangle
{
private:
int w, h;
static int nTotalArea; //静态成员变量
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal(){//静态成员函数
cout<< nTotalNumber<< ","<<nTotalArea<<endl;
}
};
int CRectangle::nTotalNumber = 0;
int CRectangle::nTotalArea = 0;
// 必须在定义类的文件中对静态成员变量进行一次说明
//或初始化。否则编译能通过,链接不能通过。
- 类名::成员名CRectangle :: PrintTotal();
- 对象名。成员名CRectangle r; r.PrintTotal();
- 指针 - >成员名CRectangle * p =&r; P-> PrintTot
- 引用。成员名CRectangle&ref = r; int n = ref.nTotalNumber
- 注意其初始化方法int CRectangle :: nTotalNumber = 0; int CRectangle :: nTotalArea = 0;
//必须在定义类的文件中对静态成员变量进行一次说明
//或初始化。否则编译能通过,链接不能通过。
成员对象和封闭类:
类,函数,对象,成员对象,继承的概念:https://blog.youkuaiyun.com/qq_37474693/article/details/78165962
- 类是一个抽象的概念,是对某一类事物的抽象。举一个例子,可以把人类看作一个类,这个类的共性有:第一、站立行走,第二、有一个很发达的大脑,上面这两点都是静态的,描述的是客观的属性(成员)。人类还需要吃饭、需要睡觉,上面这两点都是动态的行为,即方法(methods)。类可以包含函数,函数在类中就是动态的行为,即方法。
- 对象就是类的实例化,人类是一个类,而每一个人就是人类的实例化,即每一个人就是一个对象,对象具有类的属性及方法(每个人都站立行走、有一个发达的大脑,并且需要吃饭睡觉)。
-
成员对象:有一个类的一些成员是其他类的对象。
- 这样来解释继承(inheritance)也就很简单了,继承是小的类来继承大的类。比如刚刚的人类是就是一个很大的类,那学生就是一个比较小的类,学生类可以继承人类这个类,继承之后,学生就具有人类所含有的属性方法(站立行走、有一个发达的大脑,需要吃饭睡觉),此外,学生类由于是一个更小的类,所以也有一些人类所不具有的特性,即更加细化,比如学生类具有去学校上学这个行为,但人类就不具有。反过来,人类和动物类相比,人类是一个小类,动物类是一个大类,人类可以继承动物类。人类会具有动物类的一些属性,比如会死亡。
封闭类:
有成员对象的类叫 封闭(enclosing)类。
举例:
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(){}
CCar(int p,int tr,int tw );
};
CCar::CCar(int p,int tr,int w):price(p),tyre(tr, w)//一定要在这里对tyre初始化,因为tyre没有无参构造函数
{
};
int main()
{
CCar car(20000,17,225);
CCar car1;//编译出错,因为tyre初始化出错,engine初始化没出错他有默认的无参构造函数
return 0;
}
注意点:
- 任何生成封闭类对象的语句,都要让编译器明白,对象中的成员对象,是如何初始化的。
- 具体的做法就是:通过封闭类的构造函数的初始化列表。
- 成员对象初始化列表中的参数可以是任意复杂的表达式,可以包括函数,变量 ,只要表达式中的函数或变量有定义就行。
//CCar::CCar(int p,int tr,int w):price(p),tyre(tr, w)其中p,tr,w可以为函数,变量
封闭类构造函数和析构函数的执行顺序:
- 封闭类对象生成时,先执行所有对象成员的构造函数(因为封闭类构造函数可能用的到对象成员),然后才执行封闭类的构造函数。
- 对象成员的构造函数调用次序和对象成员在类中的说明次序一致,与它们在成员初始化列表中出现的次序无关。
- 当封闭类的对象消亡时,先执行封闭类的构构函数。然后再执行成员对象的分构相反。封闭类构造函数和构造函数的调用次序相反。
举例:
class CTyre {
public:
CTyre() { cout << "CTyre contructor" << endl; }
~CTyre() { cout << "CTyre destructor" << endl; }
};
class CEngine {
public:
CEngine() { cout << "CEngine contructor" << endl; }
~CEngine() { cout << "CEngine destructor" << endl; }
};
class CCar {
private:
CEngine engine;
CTyre tyre;
public:
CCar( ) { cout << “CCar contructor” << endl; }
~CCar() { cout << "CCar destructor" << endl; }
};
int main(){
CCar car;
return 0;
}
输出结果:
CEngine contructor
CTyre contructor
CCar contructor
CCar destructor
CTyre destructor
CEngine destructor
C ++中一般先初始化的后消亡,先构造的后析构
常量成员函数:
如果不希望某个对象的值被改变,则定义该对象的时候可以在前面加const关键字。
类在成员的函数说明后面可以加const的关键字,该则成员函数成为常量成员函数。
常量成员函数执行期间,不应修改其所作用的对象。成员常量函数内部不能改变成员变量的值(静态成员变量除外),也不能调用非常量成员函数(静态成员函数除外)。
class Sample {
public :
int value;
public:
void func() { };
Sample() { }
void GetValue() const {
value = 0; // wrong
func(); //wrong
}
};
const Sample Obj;
Obj.SetValue (); //常量对象上可以使用常量成员函数
常量成员函数的重载:两个函数,名字和参数表都一样,但是一个是常量,一个不是,算重载。
#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() ;
return 0;
}
=>1,2
友元函数:
为友元函数和友元类两种
1)友元函数:一个类的友元函数可以访问该类的私有成员
class CCar ; //提前声明 CCar类,以便后面的CDriver类使用
class CDriver
{
public:
void ModifyCar( CCar * pCar) ; //改装汽车,一定要是指针
};
class CCar
{
private:
int price;
friend int MostExpensiveCar( CCar cars[], int total); //声明友元
friend void CDriver::ModifyCar(CCar * pCar); //声明友元
};
void CDriverer::ModifyCar( CCar * pCar)
{
pCar->price += 1000; //汽车改装后价值增加
}
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;
}
int main()
{
return 0;
}
友元类:如果A是B的友元类,那么A的成员函数可以访问B的私有成员。
class CCar
{
private:
int price;
friend class CDriver; //声明CDriver为友元类
};
class CDriver
{
public:
CCar myCar;
void ModifyCar() {//改装汽车
myCar.price += 1000;//因CDriver是CCar的友元类,
//故此处可以访问其私有成员
}
};
int main(){ return 0;}
友元类之间的关系不能传递,不能继承。 (A是B的友元,B是C的友元,不能推导出A是C的友元)