多态常见习题

选择

1.关于虚函数说法正确的是( B)

A.被virtual修饰的函数称为虚函数  //被virtual修饰的成员函数称为虚函数

B.虚函数的作用是用来实现多态

C.虚函数在类中声明和类外定义时候,都必须加虚拟关键字 //虚函数不能在类外定义实现

D.静态虚成员函数没有this指针  // static与virtual不能同时使用

2.关于不能设置成虚函数的说法正确的是(D )

A.友元函数可以作为虚函数,因为友元函数出现在类中 //友元函数不属于成员函数,不能成为虚函数

B.成员函数都可以设置为虚函数 //静态成员函数就不能设置为虚函数

C.静态成员函数不能设置成虚函数,因为静态成员函数不能被重写 //静态成员函数与具体对象无关,属于整个类,核心关键是没有隐藏的this指针,可以通过类名::成员函数名 直接调用,此时没有this无法拿到虚表,就无法实现多态,因此不能设置为虚函数,不是因为其不能被重写

D.析构函数建议设置成虚函数,因为有时可能利用多态方式通过基类指针调用子类析构函数

3.关于多态,说法不正确的是(C )

A.C++语言的多态性分为编译时的多态性和运行时的多态性 //多态分为编译时多态和运行时多态,也叫早期绑定和晚期绑定

B.编译时的多态性可通过函数重载实现 //编译时多态是早期绑定,主要通过重载或者模板实现

C.运行时的多态性可通过模板和虚函数实现 //模板属于编译时多态

D.实现运行时多态性的机制称为动态绑定

4.要实现多态类型的调用,必须( D)

A.基类和派生类原型相同的函数至少有一个是虚函数即可 //必须是父类的函数设置为虚函数

B.假设重写成功,通过指针或者引用调用虚函数就可以实现多态 //必须通过父类的指针或者引用才可以,子类的不行

C.在编译期间,通过传递不同类的对象,编译器选择调用不同类的虚函数 //不是在编译期,而应该在运行期间

D.只有在需要实现多态时,才需要将成员函数设置成虚函数,否则没有必要

5.关于重载、重写和重定义的区别说法正确的是(A,F )【不定项选择】

A.重写和重定义都发生在继承体系中

B.重载既可以在一个类中,也可以在继承体系中 //重载只能在一个范围内,不能在不同的类里

C.它们都要求原型相同 //只有重写要求原型相同

D.重写就是重定义 //重写和重定义是两码事,重写即覆盖,针对多态, 重定义即隐藏

E.重定义就是重写

F.重写比重定义条件更严格

G.以上说法全错误

6.关于抽象类和纯虚函数的描述中,错误的是 (D )

A.纯虚函数的声明以“=0;”结束 //纯虚函数的声明以“=0;”结束,这是语法要求

B.有纯虚函数的类叫抽象类,它不能用来定义对象 //有纯虚函数的类叫抽象类,它不能用来定义对象,一般用于接口的定义

C.抽象类的派生类如果不实现纯虚函数,它也是抽象类 //子类不实现父类所有的纯虚函数,则子类还属于抽象类,仍然不能实例化对象

D.纯虚函数不能有函数体 //纯虚函数可以有函数体,只是意义不大

 

10.假设A为抽象类,下列声明(B )是正确的

A.A fun(int); //抽象类不能实例化对象,所以以对象返回是错误

B.A*p; //抽象类可以定义指针,而且经常这样做,其目的就是用父类指针指向子类从而实现多态

C.int fun(A); //参数为对象,所以错误

D.A obj; //直接实例化对象,这是不允许的

11. 下面哪种面向对象的方法可以让你变得富有(A )
A: 继承 B: 封装 C: 多态 D: 抽象

12. ( D)是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联于具体的对象。
A: 继承 B: 模板 C: 对象的自身引用 D: 动态绑定 //多态

13. 面向对象设计中的继承和组合,下面说法错误的是?(C)
A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复
用,也称为白盒复用
B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动
态复用,也称为黑盒复用
C:优先使用继承,而不是组合,是面向对象设计的第二原则 //
优先使用组合
D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封
装性的表现


14. 以下关于纯虚函数的说法,正确的是(A )
A:声明纯虚函数的类不能实例化对象 B:声明纯虚函数的类是虚基类
C:子类必须实现基类的纯虚函数 D:纯虚函数必须是空函数


15. 关于虚函数的描述正确的是(B )
A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型 //
虚函数重写要求函数名,函数参数一致

B:内联函数不能是虚函数

C:派生类必须重新定义基类的虚函数 //不一定

D:虚函数可以是一个static型的函数 //virtual与static不能同时使用


16. 关于虚表说法正确的是(D )
A:一个类只能有一张虚表 //
子类继承了多个父类时则有多张

B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表 //基类,子类不共用虚表

C:虚表是在运行期间动态生成的 //虚函数表里的内容是在编译时期由编译器生成的

D:一个类的不同对象共享该类的虚表

17. 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则(D )
A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址 //
B继承了A,它前四字节也是虚表地址

B:A类对象和B类对象前4个字节存储的都是虚基表的地址 //虚表中存储的是调用虚函数的偏移量

C:A类对象和B类对象前4个字节存储的虚表地址相同 //B重写了虚函数,不是同一张表

D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表


18. 下面程序输出结果是什么? (A)

#include<iostream>
using namespace std;
class A{
public:
A(char *s) { cout<<s<<endl; }
~A(){}
};
class B:virtual public A
{
public:
B(char *s1,char*s2):A(s1) { cout<<s2<<endl; }
};
class C:virtual public A
{
public:
C(char *s1,char*s2):A(s1) { cout<<s2<<endl; }
};
//注意A是最先初始化的
class D:public B,public C
{
public:
D(char *s1,char *s2,char *s3,char *s4):B(s1,s2),C(s1,s3),A(s1)
{ cout<<s4<<endl;}
};
int main() {
D *p=new D("class A","class B","class C","class D");
delete p;
return 0;
}

A:class A class B class C class D B:class D class B class C class A
C:class D class C class B class A D:class A class C class B class D


19. 多继承中指针偏移问题?下面说法正确的是(C )

class Base1 {  public:  int _b1; };
class Base2 {  public:  int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };
int main(){
Derive d;
Base1* p1 = &d;
Base2* p2 = &d;
Derive* p3 = &d;
return 0;
}


A:p1 == p2 == p3 B:p1 < p2 < p3 C:p1 == p3 != p2 D:p1 != p2 != p3


20. 以下程序输出结果是什么(B)
 

class A
 {
 public:
   virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
virtual void test(){ func();}
 };
 class B : public A
 {
 public:
   void func(int val=0){ std::cout<<"B->"<< val <<std::endl; }
 };
 int main(int argc ,char* argv[])
 {
   B*p = new B;
   p->test();
   return 0;
 }

A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确

// 首先func函数构成了多态(虚函数重写了,也是使用的父类的指针调用的),最后发生的情况为,func函数的定义为父类的定义,而函数体为子类的(重写只是重写了函数体)

问答题

1. 什么是多态?

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

2. 什么是重载、重写(覆盖)、重定义(隐藏)?

重载:两个函数在同一作用域,函数名相同,参数不同,构成重载

重写:两个函数为父子类,函数的名称和参数必须相同,并且必须为虚函数

隐藏:两个函数为父子类,函数名相同,参数不同

3. 多态的实现原理?

1). 必须通过基类的指针或者引用调用虚函数
2). 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

4. inline函数可以是虚函数吗?

答:可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去。

5. 静态成员可以是虚函数吗?

答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。

6. 构造函数可以是虚函数吗?

答:不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。

7. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?

答:可以,并且最好把基类的析构函数定义成虚函数。

8. 对象访问普通函数快还是虚函数更快?

答:首先如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。

9. 虚函数表是在什么阶段生成的,存在哪的?

答:虚函数表是在编译阶段就生成的,一般情况下存在代码段(常量区)的。

10.C++菱形继承的问题?虚继承的原理?

答:菱形继承有数据冗余和二义性的问题,虚继承这里是通过了父类1和父类2的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量
可以找到下面的父类1和父类2的共同的基类

11.什么是抽象类?抽象类的作用?

答:在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口
类),抽象类不能实例化出对象。

抽象类强制重写了虚函数,另外抽象类体现出了接口继承关系。

  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值