21天学通C++--阅读笔记3

数组

数组是数据存放地址的集合,每个地址保存相同类型的数据。

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.上升:methodBmethodC均提升到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 BC必须在它们的构造函数中初始化D,但当初始化C时,AB初始化将被忽略。

C对象调用methodComm时,不必再明确methodComm为哪一个基类的方法

 

注:不建议使用多重继承,一是许多编译器不支持多重继承,二是增加代码的复杂度

 

混合继承

单一继承与多重继承之间的一种折中方式,

classC:public A,B

其中,A为正常类,B类为混合继承类(功能类),该类没有货只有很少的数据。

 

抽象数据类型(虚基类)

含有纯虚函数的类为抽象数据类型(ADT),实例化该类型是非法的。

其他类继承该类时,必须覆盖所有纯虚函数,否则也为抽象数据类型。

纯虚函数:virtual void method() = 0;

 

注:一般情况下,ADT作为接口声明使用,不对纯虚函数进行实现。

规则:对所有子类必须实现的函数设为纯虚函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值