零、C++程序的基本手写法:
一、变量生存期:
分为:static静态生存期(程序开始分配、程序结束收回,如:全局变量),auto自动生存期(在程序执行到定义的语句时才分配,复合语句结束时收回,如:局部变量和函数)和register动态生存期(用New操作或调用函数malloc进行分配、用delete操作或调用函数free收回)。
二、函数名重载:
函数的名字相同,但是参数必须要不同,参数的类型或者个数要不同(因为调用者是根据实参的类型来决定调用的函数)。
例如下面这题:正确答案选B。因为(1)和(4)的参数个数和类型相同,编译器无法判定调用的是哪个函数。
三、引用类型:
引用类型相当于是给变量取了一个别名,本身没有自己的内存空间,占用的是赋值变量的内存空间,注意定义引用变量必须要有初始化,定义的格式为:<类型> &<引用变量名>=<变量>。引用类型还可以作为函数的形参和返回值。
四、this指针:
this指针主要是为了解决成员函数识别操作对象的问题,成员函数一般会有一个隐藏的this指针,指针类型定义:<类名> *const this,this指针不能够修改,但给以给其它变量赋值,静态成员函数中无this指针。a.g(1)会被按g(&a,1)的形式进行编译。
五、继承:
单继承的定义:
class <派生类名>:<继承方式> <基类名>{
<成员说明表>
}
说明:<继承方式>可以是public、private、protected,它用于说明从基类继承来的成员在派生类中的访问控制。
派生类不能直接访问基类的私有成员,必须要通过基类的非私有成员函数来访问基类的私有成员。
protected成员访问控制来缓解继承与数据封装的矛盾,在基类中声明为protected的成员可以被派生类使用,但它不能基类的实例用户使用。一般情况下,应该把日后不太可能发生变化、有可能被派生类使用的、不宜对实例用户公开的成员声明为protected。
注意访问基类成员除了要受到基类成员访问控制的限制之外,还要受到标识符作用域的限制。
在定义派生类时需要指出继承的方式,继承的方式可以是public、private以及protected,如果未显式指出,则默认为private。
继承方式的含义如下:继承方式为public:基类的public成员,在派生类中成为public成员;基类的protected成员,在派生类中成为protected成员;基类的private成员,在派生类中成为不可访问的成员。private继承基类的public、protected成员在派生类中都是private成员,private成员在派生类中成为不可使用的成员。protected继承基类的public、protcted成员在派生类中都是protected成员,private成为不可使用的成员。
在任何继承方式中除了基类的private成员,其他成员都可以在派生类中分别调整其访问控制,调整时采用下面的语句:
[public:|protected:|private:]
<基类名>::<基类成员名>
基类的指针变量可以指向派生类的对象,但派生类的指针变量不能指向基类的对象(因为它可能执行基类不能处理的消息)。派生类的对象可以赋值给基类的对象,属于派生类但不属于基类的数据成员将被忽略,但基类对象不能赋值给派生类对象,因为会导致派生类中不确定的成员数据。
如果一个类既有基类又有成员对象类,则在创建该类对象时,该类的构造函数先是调用基类的构造函数,再调用成员对象类的构造函数,最后执行自己的函数体。当该类的对象消亡时,先调用和执行自己的析构函数,然后调用成员对象类的析构函数,最后调用基类的析构函数。
六、类模板
模板函数的定义:
template <class T>
<返回值类型> <函数名>(<参数列表>)
{.....}
返回值类型和参数列表都的类型都可以是T。
类模板的定义:
template <class T1,class T2,....>
class <类名>{
<类成员声明>
}
对于在类外的成员函数的定义方法:
template <class T1,class T2>
<返回值类型> <类名> <T1,T2,...>::<成员函数名>(<参数表>)
{...}
七、成员初始化列表:
对于常量(const)数据成员和引用(&)类型数据成员,不能在说明时进行初始化,也不能采用赋值操作操作进行初始化。
可以在函数头和函数体之间加入一个对数据成员进行初始化的表,称为成员初始化表,例如:
A():z(x),y(1){x=0;}相当于将数据成员y初始化为1,数据成员z初始化为x。
注意一点:数据成员的初始化顺序由它们在类定义中说明的次序决定。
八、拷贝构造函数:
拷贝构造函数原型:
<类名>(const <类名>& <变量名>)
其中const可以省略,使用的情况是:把对象作为值传递给函数时,把对象作为值返回时。
赋值兼容:派生类的对象可以赋值给基类的对象(因为派生类的存储空间大于基类的存储空间,如果反过来赋值会导致派生类对象中出现一些未赋值或不确定的成员)。
看下面的例子:输出的结果是:Base::Print。虽然obj是派生类对象,但由于fun()函数接收的是基类引用,所以相当于将一个派生类的对象赋值给了基类,所以输出的是基类的Print函数,这点一定要小心。
多态的定义:在同一个接口(如函数)下为不同的对象服务,能被解释为不同的意义。即同样的消息被不同类型的对象接收时,能产生完全不同的行为(调用同名但不同功能的函数)。
多态的实现需要满足两个条件:继承和虚函数。
虚函数:虚函数是指在基类中定义的函数,可以在派生类中进行重写。如果基类中某个函数被声明为虚函数,在调用这个函数时,会根据实际对象的类型来确定调用哪个版本的函数。
说明一下:类型指的是返回值的类型。
虚基类:在多重继承中,如果派生类中有多个基类,而这些基类中又有公共的基类,则可以使用虚基类来解决二义性的问题。
纯虚函数:纯虚函数是指在基类中声明的一个虚函数,但没有提供具体的实现,需要在派生类中进行实现。
抽象类:含有纯虚函数的类称为抽象类。抽象类只能作为派生其它类的基类,而不能创建抽象类的对象。抽象类是不能被实例化的类。只能通过派生类来实例化,只能被用作基类来派生出其他类。
成员函数:是指定义在类中的函数,可以访问类的私有成员和保护成员。
友元函数:是定义在类外部,但可以访问类的私有成员和保护成员的非成员函数。
多态调用借助于:指向对象的基类指针或引用调用一个虚函数。
请描述多继承中出现的二义性问题及解决措施?
答:二义性问题:指在派生类中,如果同时从多个基类继承同名的成员函数或变量,会导致编译器无法确定调用哪个基类的成员,从而产生歧义。
解决方案:1、虚继承:通过将共同基类声明为虚基类,可以使得派生类只包含一份共同基类的成员,从而避免了二义性问题。2、消除二义性:通过在派生类中重新定义同名的成员函数或变量,可以消除二义性问题。
请描述重复继承中出现的二义性问题及解决措施?
答:二义性问题:在派生类中,从不同路径继承了同一个基类,会导致派生类中包含了多份基类的成员。(加入基类B1和基类B2都继承自基类B,若派生类继承自B1和B2则D中包含了两份B的成员,此时编译器无法确定调用哪一个。)
解决方案:1、虚继承:通过将共同基类声明为虚基类,可以使得派生类只包含一份共同基类的成员。2、使用作用域解析运算符:在派生类中,可以使用作用域解析运算符::来指定调用哪个基类的成员。
请描述虚基类、虚函数的功能
答:虚基类:多重继承中用来解决二义性问题的一种技术。当一个类被声明为虚基类时,它的派生类中只包含一份该类的成员,这样就避免了在多重继承中出现同名成员的二义性问题。使用关键字virtual来实现。
虚函数:实现运行时多态性的一种技术。当一个类的成员函数被声明为虚函数时,它可以在派生类中被重写,从而实现不同的行为。在运行时,程序会根据指针或引用所指向的对象的实际类型,动态地调用对应的虚函数,从而实现多态性。
请描述虚基类机制下的构造函数的执行顺序
按照继承顺序,从最顶层的基类开始,先执行基类的构造函数,再执行虚基类的构造函数(只会被执行一次),然后执行非虚基类的构造函数,最后执行派生类构造函数。(如果有多个基类,按照在类中的声明顺序执行。)
请描述虚函数动态绑定是如何实现的
根据对象实际类型,通过虚函数表,决定使用哪个虚函数的实现。虚函数表在编译期间生成,当创建 一个对象会分配一块空间来存储虚函数表的指针,这个指针会指向该对象所属的类的虚函数表。当调用一个虚函数时,会通过该对象的虚函数表指针找到该对象所属类的虚函数表,然后查找对应的虚函数的地址,最终调用该函数。
1、B
2、B
3、B 变量生存周期 p102-104
4、A
5、B 函数重载 p115-118
6、D
7、C 引用赋值 p190-194
8、B D this指针 p213-215
9、D
10、D
11、B A 函数重载 p239-237
p238-257
12、C A 继承方式P265-273
13、D C 继承方式
14、C
15、C
16、B
17、A 类模板定义 P296-301
18、A D
19、A
20、C
二1、 [1] int y,int m,int d 因为有带默认值所以应该是:int y=2019,int m=1,int d=1
[2]date d1 注意是拷贝构造函数,所以是 const date& d1
考察:继承先后次序:P271-274
基类和成员对象的构造顺序是由它们在类定义中的顺序决定的,第二次输出"constructing B2"是因为C类中有一个B2类型的成员变量memberB2。
二2、[3]constructing B11
[4]constructingB2
[5]constructingB12
[6]constructingB2