数组
数组是数据存放地址的集合,每个地址保存相同类型的数据。
int intArray[10];//int类型为4个字节,编译器会分配4*10个字节的连续内存给该数组
数组初始化
int intArray[2]; | //一维数组声明 |
int intArray[2] = {1, 2}; | //对两个元素都赋值 |
int intArray[2] = {1}; | //只对第一个元素赋值,第二个默认为0 |
int intArray[] = {1, 2}; | //不指定数组大小,根据初始值设定大小 |
XXX xArray[2]; | //需有不带参数的默认构造函数,否则xArray数组的元素为空,即不能创建对象 |
int xArray[2][3]; | //二维数组声明 |
int xArray[2][3] = {1,1,...} | //对2*3个元素进行初始化 |
int xArray[2][3] = {{1,1},...} | //用大括号对初始值分组 |
数组内存
堆栈内存是有限的,而自由存储区的内存则大很多,所以在自由存储区声明对象
1.XXX xxx[50];//对象数组
2.栈中存储数组,堆中存储对象
XXX *xxx[50];//数组存放在堆栈中,数组存放指向对象的指针,指针数组
XXX *x;
for(i<50;..){
x = new XXX;//对象存放在自由存储区
xxx[i] = x;
}
3.堆中存储数组和对象
XXX *xxx = new XXX[50];//数组指针,指向对象数组的指针,该对象数组同1定义
销毁:delete []xxx;///销毁数组,如果delete xxx;则为销毁数组中的第一个对象
字符数组
char cArray[] = "Hello world!";//编译器自动增加空字符
charcBuff[20];
cin>>cBuff;
cin.get(cBuff,19);
注:cin输入字符串时,遇到空格或换行则停止向缓冲区写入,而且当定义的缓冲区大小小于输入字符数时会溢出写入。get方法会读取固定长度的字符到缓冲区,不会造成以上两种情况。
字符数组复制
charcArray[] = "Hello world!";
charcBuff[20];
strcpy(cBuff,cArray);
strncpy(cBuff,cArray, 19);
strcpy(desStr, srcStr);//字符数组复制,如果长度srcStr>desStr,则会溢出写入
strncpy(desStr, srcStr, maxLen);//将srcStr空字符\0之前的字符或者前maxLen个字符复制到desStr
链表
不良的数组大小定义会造成空间浪费或分配不足等问题
采用链表动态分配所需要的存储空间
每个节点定义指向下一个节点的指针
单一继承
classB:public A{methodB();}
classC:public A{methodC();}
需要创建对象,既能执行B::methodB,又能执行C::methodC
1.上升:methodB和methodC均提升到A中,但会破坏类的封装性,增加类A的复杂度
2.下降:RTTI(Runtime Type Identification,运行类型鉴定),eg:为调用methodC方法下降C类
classB{methodB();}
classC:public B{methodC();}
B objB =new B;
B objC =new C;
C objT1 = dynamic_cast<C*>objB; //为空
C objT2 = dynamic_cast<C*>objC; //不为空,正常C类对象,可调用methodC方法
注: 不建议使用此种方式,应采用虚函数、模板或多重继承来实现。
多重继承
class C :public A,B
构造函数调用:A,B,C
析构函数调用:C,B,A
class A {void methodComm(); }
class B {void methodComm(); }
或者
class A :D { void methodComm(); }
class B :D { void methodComm(); }
A,B由于继承自同一个类或者定义了同名方法methodComm时,C中需显式指出调用的是哪一个类的方法。
objC->A::mehtodComm();
或者,C类覆盖methodComm方法。
第二种情况,在初始化C类对象时,构造函数调用:D,A,D,B,C,此时,有两个D类副本
即:A->D ; B->D ; C->A,B
虚继承
一般类的构造函数只初始化字节的变量和基类,但虚继承的基类是个例外,该基类由派生性最强的类初始化。
class D{void methodComm(); }
class A :virtual public D
class B :virtual public D
class C :public A, B
注:A, B,C必须在它们的构造函数中初始化D,但当初始化C时,A,B初始化将被忽略。
C对象调用methodComm时,不必再明确methodComm为哪一个基类的方法
注:不建议使用多重继承,一是许多编译器不支持多重继承,二是增加代码的复杂度
混合继承
单一继承与多重继承之间的一种折中方式,
classC:public A,B
其中,A为正常类,B类为混合继承类(功能类),该类没有货只有很少的数据。
抽象数据类型(虚基类)
含有纯虚函数的类为抽象数据类型(ADT),实例化该类型是非法的。
其他类继承该类时,必须覆盖所有纯虚函数,否则也为抽象数据类型。
纯虚函数:virtual void method() = 0;
注:一般情况下,ADT作为接口声明使用,不对纯虚函数进行实现。
规则:对所有子类必须实现的函数设为纯虚函数。