一、选择题
首先,A* p = new B;这里会调用B的构造函数,B是A的子类,所以构造B的时候会先调用A的构造函数,但是在A的构造函数中会调用bar()函数,而bar是虚函数,又满足是父类的指针调用,理应完成多态。但实际上,**在构造函数没有执行完的时候是不会执行多态机制的!!原因如下:
- 因为虚表指针是在有虚函数的情况下编译器自动添加的一个成员,它在初始化列表进行初始化的
- 子类调用构造函数时,会先调用基类构造函数。此时未执行子类构造,子类的虚表指针还没有完成初始化,也就是说子类的虚表还没有构造完成。所以无法完成多态机制
所以newB的时候首先调用A类的bar()函数,输出bar
然后p->foo调用A类的foo函数(不满足多态)输出foo
最后p->bar调用B类重写的bar函数(多态调用)输出b_bar
所以答案为A
关于构造函数中调用虚函数问题,详见这篇文章:C++构造函数中调用虚函数为什么不构成多态
A: 纯虚函数的声明以"=0"结束,✔
B:有纯虚函数的类叫抽象类,不能定义对象,✔
C:抽象类的派生类如果不是先纯虚函数,也是抽象类(因为会继承) ✔
D:纯虚函数可以有函数体 ❌
如: virtual void func() = 0
{}
对于本体,要明确两个概念:接口继承和实现继承
接口继承:就是派生类只继承函数的接口,也就是声明
实现继承,就是派生类同时继承函数的接口和实现
一般而言的继承都是实现继承:父类中的函数会整个继承给子类使用
但对于虚函数而言,父类的虚函数继承给子类。子类对虚函数的重写实际上重写的是函数的实现,也就是重新给函数体! 所以,虚函数的声明还是用的父类的声明,如果虚函数有缺省参数,自然使用的也是父类的参数。
题目中,子类没有test函数,p->test()调用父类的test,test中调用func,func满足多态调用,调用子类重写的func,但是由于重写的是func的函数体,func的声明还是父类的声明,所以func的缺省参数还是父类中的val=1,所以输出B->1
改题目是有点问题的:
首先,这段代码运行是会报错误的!(在delete a时出错)
原因:
A中没有虚函数,没有虚指针,B继承A,B中有虚指针
A是父类,B是子类
v_ptr一般在整个对象的最开始,delete a的时候,父类中是没有v_ptr成员的,所以delete的会意外的释放v_ptr这个不属于父类的空间,就会产生空间非法访问错误
如果父类有一个虚函数,父类就有一个v_ptr,就不会报错!
对于这个题,应该是运行时错误(崩溃)
二、编程题
手套
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right) {
// write code here
int left_sum=0,left_min=INT_MAX;
int right_sum=0,right_min=INT_MAX;
int zero_sum = 0; //记录数量为0的手套导致无法配对的数量
//遍历数组(左右数组一样长)
for(size_t i = 0;i<n;++i)
{
//如果有一个是0
if(left[i]*right[i]==0)
{
zero_sum+=left[i]+right[i]; //反正有一个为0 全加上即可
}
else
{
left_sum += left[i];
right_sum += right[i];
left_min= min(left_min,left[i]);
right_min = min(right_min,right[i]);
}
}
return zero_sum + min(left_sum-left_min+1,right_sum-right_min+1) + 1;
}
};